﻿#include "pch.h"
#include "scfun.h"
#include "vitdec.h"
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <float.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
void Demapping(const Ipp32fc* Input, int LenInput, const Ipp32fc* Table, int M, Ipp8u* Output)
{
    int Q = static_cast<int>(std::log2(M)); // 每个符号的比特数
    int outputIndex = 0; // 输出比特流的索引

    for (int i = 0; i < LenInput; i++) {
        // 查找 Input[i] 在 Table 中的最近匹配点
        Ipp32f minDist = FLT_MAX;
        int Position = 0;

        for (int j = 0; j < M; j++) {
            Ipp32f dist;
            ippsNormDiff_Inf_32fc32f(&Input[i], &Table[j], 1, &dist); // 计算距离
            if (dist < minDist) {
                minDist = dist;
                Position = j;

            }
        }
        // 根据 Position 获取对应的比特表示，存储到 Output
        switch (Q) {
        case 1: // BPSK
            Output[outputIndex++] = Position == 0 ? 0 : 1;
            break;

        case 2: // QPSK
            switch (Position) {
            case 0:
                Output[outputIndex++] = 0;  // 低位比特
                Output[outputIndex++] = 0;  // 高位比特
                break;
            case 1:
                Output[outputIndex++] = 1;  // 低位比特
                Output[outputIndex++] = 0;  // 高位比特
                break;
            case 2:
                Output[outputIndex++] = 0;  // 低位比特
                Output[outputIndex++] = 1;  // 高位比特
                break;
            case 3:
                Output[outputIndex++] = 1;  // 低位比特
                Output[outputIndex++] = 1;  // 高位比特
                break;
            default:
                // 如果有其他情况，这里可以处理错误或其他映射方式
                break;
            }
            break;

        case 3: // 8PSK
            Output[outputIndex++] = (Position & 0b100) >> 2; // 最高位
            Output[outputIndex++] = (Position & 0b010) >> 1; // 中间位
            Output[outputIndex++] = Position & 0b001;        // 最低位
            break;

        case 4: // 16QAM
            Output[outputIndex++] = (Position & 0b1000) >> 3; // 最高位
            Output[outputIndex++] = (Position & 0b0100) >> 2;
            Output[outputIndex++] = (Position & 0b0010) >> 1;
            Output[outputIndex++] = Position & 0b0001;        // 最低位
            break;

        default:
            // 不支持的调制方式
            break;
        }
    }
}

void SC_FIR(Ipp32fc* src, Ipp32s srclen, Ipp32fc* taps, Ipp32s tapslen, Ipp32fc* dst)
{
    IppsFIRSpec_32fc* pSpec;
    Ipp8u* buf;
    int             specSize, bufSize;
    IppStatus status;
    //get sizes of the spec structure and the work buffer
    status = ippsFIRSRGetSize(tapslen, ipp32fc, &specSize, &bufSize);


    Ipp32fc* dly = ippsMalloc_32fc(tapslen - 1);

    pSpec = (IppsFIRSpec_32fc*)ippsMalloc_8u(specSize);
    buf = ippsMalloc_8u(bufSize);

    //initialize the spec structure
    ippsFIRSRInit_32fc(taps, tapslen, ippAlgAuto, pSpec);
    //apply the FIR filter
    ippsFIRSR_32fc(src, dst, srclen, pSpec, NULL, dly, buf);
    //释放内存
    ippsFree(dly);
    ippsFree(pSpec);
    ippsFree(buf);
}

void DownConversion_SC(Ipp32f* Syn_SigIn, Ipp32s Syn_SigLen, Ipp32fc* Syn_FIRCoe, Ipp32s Syn_FIRLen, Ipp32fc* DownSampledSig, Ipp32s va_g_f0, Ipp32s va_g_fs, Ipp32s va_N_upsample, Ipp32s va_N_g)
{
    //申请内存
    Ipp32u SigCnt = 0, delay = 0;
    Ipp32fc* MixSig = ippsMalloc_32fc(Syn_SigLen + Syn_FIRLen - 1);
    Ipp32fc* MixSigFIR = ippsMalloc_32fc(Syn_SigLen + Syn_FIRLen - 1);
    ippsZero_32fc(MixSig, Syn_SigLen + Syn_FIRLen - 1);
    ippsZero_32fc(MixSigFIR, Syn_SigLen + Syn_FIRLen - 1);

    /// Section 1: 调制到基带
    Ipp32f* VectorInt = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* SinVectorInt = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* CosVectorInt = ippsMalloc_32f(Syn_SigLen);

    Ipp32f* SigSin = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* SigCos = ippsMalloc_32f(Syn_SigLen);

    for (SigCnt = 0; SigCnt < Syn_SigLen; SigCnt++)
    {
        *(VectorInt + SigCnt) = (Ipp32f)(-2 * IPP_PI * va_g_f0 * SigCnt / va_g_fs);
    }
    //生成正弦和余弦
    ippsSin_32f_A11(VectorInt, SinVectorInt, Syn_SigLen);
    ippsMul_32f(Syn_SigIn, SinVectorInt, SigSin, Syn_SigLen);
    ippsCos_32f_A11(VectorInt, CosVectorInt, Syn_SigLen);
    ippsMul_32f(Syn_SigIn, CosVectorInt, SigCos, Syn_SigLen);

    //组合成复数信号
    ippsRealToCplx_32f(SigCos, SigSin, MixSig, Syn_SigLen);




    Ipp32fc* filteredSignal = (Ipp32fc*)ippsMalloc_32fc(Syn_SigLen + Syn_FIRLen); // 分配内存用于存储滤波结果


    SC_FIR(MixSig, Syn_SigLen + ((Syn_FIRLen - 1) / 2), Syn_FIRCoe, Syn_FIRLen, filteredSignal); // FIR 滤波，这个测试了没问题

    Ipp32fc* OutputSignal = (Ipp32fc*)ippsMalloc_32fc(Syn_SigLen);   // 分配内存用于最终输出

    delay = (Syn_FIRLen - 1); // 等效于 fix(length(PulseShape)/2)
    ippsCopy_32fc(filteredSignal + delay, OutputSignal, Syn_SigLen - (delay / 2)); // 裁剪延迟




    /// Section 2: 实现降采样
    Ipp32s LengthOutSignal = Syn_SigLen - (delay - 1) / 2;      // 滤波后的信号长度
    Ipp32s LengthAftDown = LengthOutSignal / va_N_upsample; // 降采样后的信号长度
    Ipp32fc* TempDownSampledSig = ippsMalloc_32fc(LengthAftDown);

    for (Ipp32s i = 0; i < LengthAftDown && i * va_N_upsample < LengthOutSignal; i++) {
        TempDownSampledSig[i].re = 2 * OutputSignal[i * va_N_upsample].re; // 实部乘以 2
        TempDownSampledSig[i].im = 2 * OutputSignal[i * va_N_upsample].im; // 虚部乘以 2
    }

    /// Section 3: 剔除前 N_g 个元素
    Ipp32s FinalLength = LengthAftDown - va_N_g; // 剔除后的信号长度
    if (FinalLength > 0)
    {
        ippsCopy_32fc(TempDownSampledSig + va_N_g, DownSampledSig, FinalLength);
    }

    //释放内存
    ippsFree(MixSig);
    ippsFree(MixSigFIR);
    ippsFree(VectorInt);
    ippsFree(SinVectorInt);
    ippsFree(CosVectorInt);
    ippsFree(SigSin);
    ippsFree(SigCos);
    ippsFree(TempDownSampledSig);
}

void LoadComplexData(const char* filename, Ipp32fc* data, int length)
{
    FILE* file;
    fopen_s(&file, filename, "r");
    if (!file) {
        printf("无法打开文件 %s\n", filename);
        exit(-1);
    }

    for (int i = 0; i < length; i++) {
        float real, imag;
        if (fscanf_s(file, "(%f, %f)\n", &real, &imag) != 2) {
            printf("读取文件 %s 时出错\n", filename);
            exit(-1);
        }
        data[i].re = real;
        data[i].im = imag;
    }

    fclose(file);
    printf("成功加载文件 %s\n", filename);
}

void MMSE_Equalizer(Ipp32fc* SignalRecData, int N_block, int N_data, int N_FFT, Ipp32fc* H_LS_NFFT, float SNR, Ipp32fc* Signal_DataEqu, int va_N_g)
{
    // 计算 FFT 所需的 order
    int order = (int)(log(N_FFT) / log(2));

    // 初始化 FFT 规格
    IppsFFTSpec_C_32fc* pFFTSpec = NULL;
    int sizeSpec = 0, sizeInit = 0, sizeBuf = 0;
    Ipp8u* pBuffer = NULL;

    ippsFFTGetSize_C_32fc(order, IPP_FFT_DIV_INV_BY_N, ippAlgHintFast,
        &sizeSpec, &sizeInit, &sizeBuf);

    Ipp8u* pSpec = (Ipp8u*)ippsMalloc_8u(sizeSpec);
    pBuffer = (Ipp8u*)ippsMalloc_8u(sizeBuf);

    ippsFFTInit_C_32fc(&pFFTSpec, order, IPP_FFT_DIV_INV_BY_N,
        ippAlgHintFast, pSpec, pBuffer);

    // 分配临时数组
    Ipp32fc* SignalFD_DataRec = ippsMalloc_32fc(N_block * N_FFT);
    Ipp32fc* W_LS = ippsMalloc_32fc(N_block * N_FFT);
    Ipp32fc* SignalFD_DataEqu = ippsMalloc_32fc(N_block * N_FFT);

    // 逐块处理
    for (int blk = 0; blk < N_block; blk++) {
        Ipp32fc* pSignalRecData = SignalRecData + blk * N_data;
        Ipp32fc* pSignalFD_DataRec = SignalFD_DataRec + blk * N_FFT;
        Ipp32fc* pH_LS_NFFT = H_LS_NFFT + blk * N_FFT;
        Ipp32fc* pW_LS = W_LS + blk * N_FFT;
        Ipp32fc* pSignalFD_DataEqu = SignalFD_DataEqu + blk * N_FFT;
        Ipp32fc* pSignal_DataEqu = Signal_DataEqu + blk * (N_FFT - va_N_g);

        // 步骤 1：FFT
        Ipp32fc* pInputFFT = ippsMalloc_32fc(N_FFT);
        ippsZero_32fc(pInputFFT, N_FFT);
        ippsCopy_32fc(pSignalRecData, pInputFFT, N_data);

        Ipps_FFT_32fc_SC(pInputFFT, pSignalFD_DataRec, N_FFT);


        ippsFree(pInputFFT);

        // 步骤 2：计算均衡系数 W_LS
        // 2.1 共轭
        ippsConj_32fc(pH_LS_NFFT, pW_LS, N_FFT);//pW_LS共轭

        // 2.2 计算 |H|^2 + 1/SNR
        Ipp32f* pDenominator = ippsMalloc_32f(N_FFT);
        ippsPowerSpectr_32fc(pH_LS_NFFT, pDenominator, N_FFT);

        float invSNR = 1.0 / SNR;
        ippsAddC_32f_I(invSNR, pDenominator, N_FFT);


        // 分配内存
        Ipp32fc* pDenominatorComplex = ippsMalloc_32fc(N_FFT);

        // 将 pDenominator 转换为复数，虚部设置为 0
        for (int i = 0; i < N_FFT; i++) {
            pDenominatorComplex[i].re = pDenominator[i];
            pDenominatorComplex[i].im = 0.0f;
        }

        // 2.3 W_LS = conj(H) ./ Denominator
        ippsDiv_32fc(pDenominatorComplex, pW_LS, pW_LS, N_FFT);

        ippsFree(pDenominator);
        ippsFree(pDenominatorComplex);

        // 步骤 3：频域均衡
        ippsMul_32fc(pW_LS, pSignalFD_DataRec, pSignalFD_DataEqu, N_FFT);

        // 步骤 4：IFFT
        //ippsFFTInv_CToC_32fc(pSignalFD_DataEqu, pSignalFD_DataEqu,
            //pFFTSpec, pBuffer);
        Ipps_IFFT_32fc_SC(pSignalFD_DataEqu, pSignalFD_DataEqu, N_FFT);



        // 步骤 5：去除 UW 部分
        ippsCopy_32fc(pSignalFD_DataEqu, pSignal_DataEqu, N_FFT - 0);

        // 遍历 pSignal_DataEqu，将虚部取相反数
        for (int i = 0; i < (N_FFT - 0); i++) {
            pSignal_DataEqu[i].im = -pSignal_DataEqu[i].im;
        }


    }

    // 释放资源
    ippsFree(pSpec);
    ippsFree(pBuffer);

    ippsFree(SignalFD_DataRec);
    ippsFree(W_LS);
    ippsFree(SignalFD_DataEqu);
}

void Ipps_IFFT_32fc_SC(Ipp32fc* Src, Ipp32fc* Dst, int FFTCnt)
{
    IppsFFTSpec_C_32fc* pSpec = 0;

    Ipp8u* pMemSpec = 0;
    Ipp8u* pMemInit = 0;
    Ipp8u* pMemBuffer = 0;

    int FFTOrder = 0;
    int sizeSpec = 0;
    int sizeInit = 0;
    int sizeBuffer = 0;

    int flag = IPP_FFT_NODIV_BY_ANY;
    Ipp32fc N = { FFTCnt ,0 };
    switch (FFTCnt)
    {
    case 2: FFTOrder = 1; break;
    case 4: FFTOrder = 2; break;
    case 8: FFTOrder = 3; break;
    case 16: FFTOrder = 4; break;
    case 32: FFTOrder = 5; break;
    case 64: FFTOrder = 6; break;
    case 128: FFTOrder = 7; break;
    case 256: FFTOrder = 8; break;
    case 512: FFTOrder = 9; break;
    case 1024: FFTOrder = 10; break;
    case 2048: FFTOrder = 11; break;
    case 4096: FFTOrder = 12; break;
    case 8192: FFTOrder = 13; break;
    case 16384: FFTOrder = 14; break;
    case 32768: FFTOrder = 15; break;
    case 65536: FFTOrder = 16; break;
    case 131072: FFTOrder = 17; break;
    case 262144: FFTOrder = 18; break;
    case 524288: FFTOrder = 19; break;
    case 1048576: FFTOrder = 20; break;
    case 2097152: FFTOrder = 21; break;
    case 4194304: FFTOrder = 22; break;
    default:      FFTOrder = 22; break;
    }

    // get sizes for required buffers
    ippsFFTGetSize_C_32fc(FFTOrder, flag, ippAlgHintNone, &sizeSpec, &sizeInit, &sizeBuffer);

    // allocate memory for required buffers
    pMemSpec = (Ipp8u*)ippMalloc(sizeSpec);

    if (sizeInit > 0)
    {
        pMemInit = (Ipp8u*)ippMalloc(sizeInit);
    }

    if (sizeBuffer > 0)
    {
        pMemBuffer = (Ipp8u*)ippMalloc(sizeBuffer);
    }

    // initialize FFT specification structure
    ippsFFTInit_C_32fc(&pSpec, FFTOrder, flag, ippAlgHintNone, pMemSpec, pMemInit);

    // free initialization buffer
    if (sizeInit > 0)
    {
        ippFree(pMemInit);
    }

    // 
    ippsConj_32fc_I(Src, FFTCnt);                         //
    ippsFFTFwd_CToC_32fc(Src, Dst, pSpec, pMemBuffer);  //Src的共轭做FFT
    ippsConj_32fc_I(Dst, FFTCnt);                         //输出取共轭
    ippsDivC_32fc_I(N, Dst, FFTCnt);                        //再除以N
    ippsConj_32fc_I(Src, FFTCnt);                         //
    // free buffers
    if (sizeBuffer > 0)
    {
        ippFree(pMemBuffer);
    }

    ippFree(pMemSpec);
}

void Ipps_FFT_32fc_SC(Ipp32fc* Src, Ipp32fc* Dst, int FFTCnt)
{
    IppsFFTSpec_C_32fc* pSpec = 0;

    Ipp8u* pMemSpec = 0;
    Ipp8u* pMemInit = 0;
    Ipp8u* pMemBuffer = 0;
    int FFTOrder = 0;
    int sizeSpec = 0;
    int sizeInit = 0;
    int sizeBuffer = 0;

    int flag = IPP_FFT_NODIV_BY_ANY;

    switch (FFTCnt)
    {
    case 2: FFTOrder = 1; break;
    case 4: FFTOrder = 2; break;
    case 8: FFTOrder = 3; break;
    case 16: FFTOrder = 4; break;
    case 32: FFTOrder = 5; break;
    case 64: FFTOrder = 6; break;
    case 128: FFTOrder = 7; break;
    case 256: FFTOrder = 8; break;
    case 512: FFTOrder = 9; break;
    case 1024: FFTOrder = 10; break;
    case 2048: FFTOrder = 11; break;
    case 4096: FFTOrder = 12; break;
    case 8192: FFTOrder = 13; break;
    case 16384: FFTOrder = 14; break;
    case 32768: FFTOrder = 15; break;
    case 65536: FFTOrder = 16; break;
    case 131072: FFTOrder = 17; break;
    case 262144: FFTOrder = 18; break;
    case 524288: FFTOrder = 19; break;
    case 1048576: FFTOrder = 20; break;
    case 2097152: FFTOrder = 21; break;
    case 4194304: FFTOrder = 22; break;
    default:      FFTOrder = 22; break;
    }
    // get sizes for required buffers
    ippsFFTGetSize_C_32fc(FFTOrder, flag, ippAlgHintNone, &sizeSpec, &sizeInit, &sizeBuffer);

    // allocate memory for required buffers
    pMemSpec = (Ipp8u*)ippMalloc(sizeSpec);

    if (sizeInit > 0)
    {
        pMemInit = (Ipp8u*)ippMalloc(sizeInit);
    }

    if (sizeBuffer > 0)
    {
        pMemBuffer = (Ipp8u*)ippMalloc(sizeBuffer);
    }

    // initialize FFT specification structure
    ippsFFTInit_C_32fc(&pSpec, FFTOrder, flag, ippAlgHintNone, pMemSpec, pMemInit);

    // free initialization buffer
    if (sizeInit > 0)
    {
        ippFree(pMemInit);
    }

    // perform forward FFT
    ippsFFTFwd_CToC_32fc(Src, Dst, pSpec, pMemBuffer);

    // free buffers
    if (sizeBuffer > 0)
    {
        ippFree(pMemBuffer);
    }

    ippFree(pMemSpec);
}

void SBL(const Ipp32fc* x, const Ipp32fc* Yp, int N_observations, int channel_length, int user_number, Ipp32fc* u_out, Ipp32s va_N_samp_SIMO, Ipp32s va_N_g)
{
    // 初始化参数
    int iter = 0;
    int iter_max = 20;
    float threshold_sbl = 0.00001f;
    float sbl_sigma_2 = 1.0f;
    float es = 1.0f;

    int M = channel_length * user_number;

    // 动态分配内存
    float* r = new float[M]();
    float* Tao = new float[M]();
    float* r_last = new float[M]();
    for (int i = 0; i < M; i++) {
        r[i] = 1;
        Tao[i] = 1;
        r_last[i] = 1;
    }
    Ipp32fc* phi_p_T_phi_p = ippsMalloc_32fc(M * M);
    Ipp32fc* phi_p_T_phi_p_test = ippsMalloc_32fc(M * M);
    Ipp32fc* phi_p_T_Yp = ippsMalloc_32fc(M);
    Ipp32fc* A = ippsMalloc_32fc(M * M);
    int* ipiv = new int[M * 2]();
    Ipp32fc* temp_vector = ippsMalloc_32fc(M);
    Ipp32fc* phi_p_u = ippsMalloc_32fc(va_N_samp_SIMO - va_N_g + 1);
    Ipp32fc* residual = ippsMalloc_32fc(N_observations);
    Ipp32fc* SIGMA_inv_Tao = ippsMalloc_32fc(M * M);
    // 定义 alpha 和 beta
    Ipp32fc alpha = { 1.0f, 0.0f };
    Ipp32fc beta = { 0.0f, 0.0f };

    // 检查 x 是否有效
    if (x == nullptr) {
        std::cerr << "x is null!" << std::endl;
        return;
    }
    // 计算 phi_p_T_phi_p = phi_p' * phi_p
    //cblas_cgemm(CblasRowMajor, CblasConjTrans, CblasNoTrans, 144, 144, 37,
    //    &alpha, x, 144, x, 144, &beta, phi_p_T_phi_p, M);
    cblas_cgemm(CblasRowMajor, CblasConjTrans, CblasNoTrans, va_N_g, va_N_g, va_N_samp_SIMO - va_N_g + 1,
        &alpha, x, va_N_g, x, va_N_g, &beta, phi_p_T_phi_p, M);

    // 计算 phi_p_T_Yp = phi_p' * Yp
    cblas_cgemm(CblasRowMajor, CblasConjTrans, CblasNoTrans,
        va_N_g, 1, va_N_samp_SIMO - va_N_g + 1, // M, N, K
        &alpha, // 乘法的标量系数
        x, va_N_g, // 矩阵 phi_p 的地址和列主存储中每行的步长 (LDA)
        Yp, 1,  // 矩阵 Yp 的地址和列主存储中每行的步长 (LDB)
        &beta, // 加法的标量系数
        phi_p_T_Yp, 1); // 结果存储的位置和步长 (LDC)
    // 主循环
    while (es > threshold_sbl && iter < iter_max) {
        // A = (1/sbl_sigma_2) * phi_p_T_phi_p + inv(Tao)
        ippsCopy_32fc(phi_p_T_phi_p, A, M * M);
        Ipp32fc scalar = { 1.0f / sbl_sigma_2, 0.0f };
        //ippsScale_32fc_I(scalar, A, M * M);
        ippsMulC_32fc(A, scalar, A, M * M);
        for (int i = 0; i < M; ++i) {
            A[i * M + i].re += 1.0f / Tao[i];
        }
        MKL_Complex8* A_MKL = (MKL_Complex8*)mkl_malloc(M * M * sizeof(MKL_Complex8), 64);
        for (int i = 0; i < M * M; ++i) {
            A_MKL[i].real = A[i].re;
            A_MKL[i].imag = A[i].im;
        }
        int info = 0;
        info = LAPACKE_cgetrf(LAPACK_ROW_MAJOR, M, M, A_MKL, M, ipiv);
        if (info != 0) {
            std::cerr << "LU decomposition failed, info = " << info << std::endl;
            break;
        }
        info = LAPACKE_cgetri(LAPACK_ROW_MAJOR, M, A_MKL, M, ipiv);
        if (info != 0) {
            std::cerr << "Matrix inversion failed, info = " << info << std::endl;
            break;
        }
        for (int i = 0; i < M * M; ++i) {
            A[i].re = A_MKL[i].real;
            A[i].im = A_MKL[i].imag;
        }
        mkl_free(A_MKL);
        // temp_vector = SIGMA * phi_p_T_Yp
        ippsZero_32fc(temp_vector, M);
        cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,//60*60和60*1的矩阵相乘
            va_N_g, 1, va_N_g, // M, N, K
            &alpha, // 乘法的标量系数
            A, va_N_g, // 矩阵 sigma 的地址和列主存储中每行的步长 (LDA)
            phi_p_T_Yp, 1, // 矩阵 phi_p_Yp 的地址和列主存储中每行的步长 (LDB)
            &beta, // 加法的标量系数
            temp_vector, 1); // 结果存储的位置和步长 (LDC)
        // u_out = (1/sbl_sigma_2) * temp_vector
        scalar = { 1.0f / sbl_sigma_2, 0.0f };
        ippsMulC_32fc(temp_vector, scalar, u_out, M);  // temp_vector * scalar -> u_out

        // 更新 r(i) = SIGMA(i,i).re + abs(u(i))^2
        for (int i = 0; i < M; ++i) {
            float abs_u_i_sq = u_out[i].re * u_out[i].re + u_out[i].im * u_out[i].im;
            r[i] = A[i * M + i].re + abs_u_i_sq;
        }
        ippsZero_32fc(phi_p_u, (va_N_samp_SIMO - va_N_g + 1));
        // 计算 phi_p_u = phi_p * u_out
        cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,//93*60和60*1的矩阵相乘
            (va_N_samp_SIMO - va_N_g + 1), 1, va_N_g, // M, N, K
            &alpha, // 乘法的标量系数
            x, va_N_g, // 矩阵 phi_p 的地址和列主存储中每行的步长 (LDA)
            u_out, 1, // 矩阵 u_out 的地址和列主存储中每行的步长 (LDB)
            &beta, // 加法的标量系数
            phi_p_u, 1); // 结果存储的位置和步长 (LDC)

        // residual = Yp - phi_p_u
        ippsSub_32fc(Yp, phi_p_u, residual, va_N_samp_SIMO - va_N_g + 1);
        // 计算残差平方和
        double norm_residual_sq;
        ippsNorm_L2_32fc64f(residual, va_N_samp_SIMO - va_N_g + 1, &norm_residual_sq);
        norm_residual_sq = norm_residual_sq * norm_residual_sq;
        // 逐元素相乘并提取实部
        double trace_s = 0;
        double* product = (double*)ippsMalloc_64f(M);
        for (int i = 0; i < M; i++) {
            trace_s += A[i * M + i].re * (1.0f / Tao[i]);// 对角元素 σ[i, i]
            product[i] = A[i * M + i].re * (1.0f / Tao[i]);
        }
        // 更新 sbl_sigma_2
        sbl_sigma_2 = abs((norm_residual_sq + sbl_sigma_2 * (M - trace_s))) / (va_N_samp_SIMO - va_N_g + 1);
        // 更新 Tao
        ippsCopy_32f(r, Tao, M);
        // 计算误差 es = norm(r - r_last)^2
        float* diff = (float*)ippsMalloc_32f(M);
        ippsSub_32f(r, r_last, diff, M);
        ippsNorm_L2_32f(diff, M, &es);
        es = es * es;
        // 更新 r_last
        ippsCopy_32f(r, r_last, M);
        iter++;
    }
    // 释放内存
    ippsFree(phi_p_T_phi_p);
    ippsFree(phi_p_T_Yp);
    ippsFree(A);
    ippsFree(temp_vector);
    ippsFree(phi_p_u);
    ippsFree(residual);
    ippsFree(SIGMA_inv_Tao);
    ippsFree(phi_p_T_phi_p_test);
}

void Rev2Cpl_SC(Ipp32f* DataRev, Ipp32s DataLen, Ipp32fc* DataCpl)
{
    Ipp32f* DataImg = ippsMalloc_32f(DataLen);
    ippsZero_32f(DataImg, DataLen);
    //组合成复数
    ippsRealToCplx_32f(DataRev, DataImg, DataCpl, DataLen);
    ippsFree(DataImg);
}

void DownConversion_BandPass(Ipp32f* SignalIn, Ipp32s SignalLen, Ipp32fc* BandPassCoe, Ipp32s FilterLen, Ipp32f* SignalOut)
{
    // SignalIn 是输入信号（实部）
    // SignalLen 是输入信号的长度
    // BandPassCoe 是带通滤波器的复数系数
    // FilterLen 是滤波器的长度
    // SignalOut 是滤波结果的实部（实数）

    // 临时缓冲区用于存储补零后的信号
    Ipp32s ExtendedLen = SignalLen + FilterLen - 1;
    Ipp32fc* TempSignal = ippsMalloc_32fc(ExtendedLen);
    ippsZero_32fc(TempSignal, ExtendedLen);
    Rev2Cpl_SC(SignalIn, SignalLen, TempSignal);

    // 临时缓冲区存储滤波结果（包含延时部分）
    Ipp32fc* FilteredSignal = ippsMalloc_32fc(ExtendedLen);

    // 调用 SC_FIR 完成滤波
    SC_FIR(TempSignal, ExtendedLen, BandPassCoe, FilterLen, FilteredSignal);

    // 移除滤波延时（等效于 MATLAB 中 fix(length(BandPass)/2)+1:end）
    Ipp32s FilterDelay = (FilterLen - 1) / 2;
    Ipp32fc* FilteredSignalAdjusted = FilteredSignal + FilterDelay;

    // 提取复数信号的实部
    ippsReal_32fc(FilteredSignalAdjusted, SignalOut, SignalLen);

    // 释放内存
    ippsFree(TempSignal);
    ippsFree(FilteredSignal);
}

void ComputePhaseDifference(Ipp32fc* input1, Ipp32fc* input2, Ipp32f* phase_diff, int length)
{
    Ipp32f* phase1 = ippsMalloc_32f(length);
    Ipp32f* phase2 = ippsMalloc_32f(length);

    // 计算两个数组的相位
    ippsPhase_32fc(input1, phase1, length);
    ippsPhase_32fc(input2, phase2, length);

    // 计算相位差
    ippsSub_32f(phase1, phase2, phase_diff, length);

    // 修正相位范围：将相位限制在 [-π/2, π/2]
    for (int i = 0; i < length; ++i) {
        if (phase_diff[i] < -IPP_PI / 2) {
            phase_diff[i] += 2 * IPP_PI;
        }
    }

    ippsFree(phase1);
    ippsFree(phase2);
}

void GroupPhaseCorrection(Ipp32fc* SignalAftEqu, int frame_num, int bitnum_per_frame, int N_samp, Ipp32fc* symbol_xl, Ipp32fc* Table, int TableSize, int block_num, Ipp32fc* symbol_parallel, Ipp32f* phi)
{
    int block_symbol = (bitnum_per_frame - N_samp) / block_num; // 每子块符号数,这里是20
    Ipp32fc* decision = ippsMalloc_32fc(block_symbol); // 存储判决后的符号
    Ipp32fc* x_zheng_parallel = ippsMalloc_32fc(block_symbol * block_num); // 分组后的并行数据，700
    Ipp32f* phase_diff = ippsMalloc_32f(N_samp);                          // 相位偏移临时存储
    Ipp64f* distance = ippsMalloc_64f(4); // 用于存储批量距离
    for (int i = 0; i < frame_num; ++i) {
        Ipp32fc* current_frame = SignalAftEqu + i * bitnum_per_frame;
        Ipp32fc* current_symbol_xl = symbol_xl + i * N_samp;

        // Step 1: 计算训练序列初始相位偏移,这里我写反了一下不知道为什么又是正确的了，先不管了能跑起来就万岁
        ComputePhaseDifference(current_symbol_xl, current_frame, phase_diff, N_samp);
        //ComputePhaseDifference(current_frame, current_symbol_xl,  phase_diff, N_samp);
        ippsMean_32f(phase_diff, N_samp, &phi[i * (block_num + 1)], ippAlgHintFast); // 初始相位偏移存储在 phi[i][0]

        // Step 2: 提取子块数据并转换到并行形式
        ippsCopy_32fc(current_frame + N_samp, x_zheng_parallel, block_symbol * block_num);

        for (int count = 0; count < block_num; ++count) {
            Ipp32fc* current_block = x_zheng_parallel + count * block_symbol;
            Ipp32fc* current_block_temp = ippsMalloc_32fc(block_symbol);//x_zheng_parallel_temp
            // 对当前子块进行相位补偿
            Ipp32fc val = { cos(phi[i * (block_num + 1) + count]), sin(-phi[i * (block_num + 1) + count]) };
            ippsMulC_32fc(current_block, val,
                current_block_temp, block_symbol);
            // 符号判决：与调制表进行最小距离匹配
            for (int num = 0; num < block_symbol; ++num) {
                Ipp32fc best_match = Table[0];
                for (int t = 0; t < TableSize; ++t) {

                    Ipp32fc* diff = ippsMalloc_32fc(2);
                    ippsSub_32fc(&current_block_temp[num], &Table[t], diff, 1);
                    ippsNorm_L2_32fc64f(diff, 1, &distance[t]);
                    ippsFree(diff);
                }
                // 使用 ippsMinIndx_64f 找到最小值和索引
                double min_distance;
                int min_index;
                ippsMinIndx_64f(distance, 4, &min_distance, &min_index);
                decision[num] = Table[min_index];
            }
            // 计算当前子块的相位偏移
            ComputePhaseDifference(decision, current_block_temp, phase_diff, block_symbol);
            ippsMean_32f(phase_diff, block_symbol, &phi[i * (block_num + 1) + count + 1], ippAlgHintFast);
            // 在 phi 数组中添加上前一个元素的值
            phi[i * (block_num + 1) + count + 1] += phi[i * (block_num + 1) + count];
            // 更新相位补偿后的数据
            ippsMulC_32fc(current_block, { cos(-phi[i * (block_num + 1) + count + 1]), sin(-phi[i * (block_num + 1) + count + 1]) },
                current_block, block_symbol);

        }

        // 串并转换并写入输出
        ippsCopy_32fc(x_zheng_parallel, symbol_parallel + i * bitnum_per_frame + N_samp, block_symbol * block_num);
        ippsMulC_32fc(current_frame, { cos(-phi[i * (block_num + 1)]), sin(-phi[i * (block_num + 1)]) },
            symbol_parallel + i * bitnum_per_frame, N_samp);
    }

    // 清理内存
    ippsFree(x_zheng_parallel);
    ippsFree(phase_diff);
    ippsFree(decision);
    ippsFree(distance);
}

void Sync_SC(Ipp32f* Syn_DataCachePrmy, Ipp32f* Syn_RefCopyAll, Ipp32s* Syn_PosSecond, Ipp32f* Syn_SigRec)
{
    //IppEnum funCfg = (IppEnum)(ippAlgDirect);
    IppEnum funCfgNormA = (IppEnum)(ippAlgFFT | ippsNormA);
    int bufSize;

    int lowLag = -((Signal_After_BP_lenth + g_LFM2Data_lenth * 2) - 1);
    ippsCrossCorrNormGetBufferSize((Signal_After_BP_lenth + g_LFM2Data_lenth * 2), (Signal_After_BP_lenth + g_LFM2Data_lenth * 2), 2 * (Signal_After_BP_lenth + g_LFM2Data_lenth * 2) - 1, lowLag, ipp32f, funCfgNormA, &bufSize);
    Ipp8u* pBuffer = ippsMalloc_8u(bufSize);


    Ipp32f* Syn_RefCopyAll_Padded = ippsMalloc_32f((Signal_After_BP_lenth + g_LFM2Data_lenth * 2));
    ippsZero_32f(Syn_RefCopyAll_Padded, (Signal_After_BP_lenth + g_LFM2Data_lenth * 2));
    ippsCopy_32f(Syn_RefCopyAll, Syn_RefCopyAll_Padded, g_LFM2Data_lenth);

    //初始化同步标志和位置
    Ipp32f* Syn2_CorrCur = ippsMalloc_32f(2 * (Signal_After_BP_lenth + g_LFM2Data_lenth * 2) - 1);
    Ipp32f* Syn2_CorrCur_Padded = ippsMalloc_32f((Signal_After_BP_lenth + g_LFM2Data_lenth * 2) + g_LFM2Data_lenth - 1);
    Ipp32f* Syn2_CorrCur_Abs = ippsMalloc_32f((Signal_After_BP_lenth + g_LFM2Data_lenth * 2) + g_LFM2Data_lenth - 1);

    //ippsConvolve_32f(
    //    Syn_DataCachePrmy,  // 输入信号 x[m]
    //    (Signal_After_BP_lenth + g_LFM2Data_lenth *2),// 信号 x 的长度
    //    Syn_RefCopyAll,  // 输入信号 y[m]
    //    g_LFM2Data_lenth,   // 信号 y 的长度
    //    Syn2_CorrCur,         // 输出结果 Rxy[n]
    //    funCfg,
    //    pBuffer
    //);

    ippsCrossCorrNorm_32f(
        Syn_RefCopyAll_Padded,// 输入信号 x[m]
        (Signal_After_BP_lenth + g_LFM2Data_lenth * 2),// 信号 x 的长度
        Syn_DataCachePrmy,  // 输入信号 y[m]
        (Signal_After_BP_lenth + g_LFM2Data_lenth * 2),   // 信号 y 的长度
        Syn2_CorrCur,         // 输出结果 Rxy[n]
        2 * (Signal_After_BP_lenth + g_LFM2Data_lenth * 2) - 1,
        lowLag,
        funCfgNormA,
        pBuffer

    );
    ippsCopy_32f(Syn2_CorrCur + (Signal_After_BP_lenth + g_LFM2Data_lenth * 2) - g_LFM2Data_lenth, Syn2_CorrCur_Padded, (Signal_After_BP_lenth + g_LFM2Data_lenth * 2) + g_LFM2Data_lenth - 1);


    ippsAbs_32f(Syn2_CorrCur_Padded, Syn2_CorrCur_Abs, (Signal_After_BP_lenth + g_LFM2Data_lenth * 2) + g_LFM2Data_lenth - 1);
    //找到相关值最大的位置，截取信号
    Ipp32f MaxAbsCur = 0;
    ippsMaxAbsIndx_32f(Syn2_CorrCur_Abs, g_fs, &MaxAbsCur, Syn_PosSecond);
    *Syn_PosSecond = *Syn_PosSecond + 1;

    //截取信号,是从原始信号的缓存数组里截取的
    ippsCopy_32f(Syn_DataCachePrmy + *Syn_PosSecond + DelayLen * 2, Syn_SigRec, g_InfoSamPointTotalSyn);

    Ipp32f maxAbsValue = 0;
    ippsMaxAbs_32f(Syn_SigRec, g_InfoSamPointTotalSyn, &maxAbsValue);
    // 对 Syn_SigRec 进行归一化
    if (maxAbsValue > 0) { // 防止除以 0
        ippsNormalize_32f(Syn_SigRec, Syn_SigRec, g_InfoSamPointTotalSyn, 0, maxAbsValue);
    }
    //释放内存
    ippsFree(Syn2_CorrCur);
    ippsFree(Syn2_CorrCur_Abs);
    ippsFree(pBuffer);
}

void Load32fData(const char* filename, Ipp32f* data, int length)
{
    FILE* file;
    fopen_s(&file, filename, "r");
    if (!file) {
        printf("无法打开文件 %s\n", filename);
        exit(-1);
    }

    for (int i = 0; i < length; i++) {
        float real;
        // 修复 fscanf_s 的返回值判断，返回值应为 1
        if (fscanf_s(file, "%f", &real) != 1) {
            printf("读取文件 %s 时出错，在第 %d 行\n", filename, i + 1);
            fclose(file);  // 关闭文件
            exit(-1);
        }
        data[i] = real;  // 存储到数组
    }

    fclose(file);
    printf("成功加载文件 %s\n", filename);
}

void SaveCharData(const char* filename, const char* data, int length)
{
    FILE* file;
    fopen_s(&file, filename, "w");
    if (!file) {
        printf("无法打开文件 %s\n", filename);
        exit(-1);
    }

    for (int i = 0; i < length; i++) {
        // 将字符写入文件，每行一个字符
        if (fprintf(file, "%c\n", data[i]) < 0) {
            printf("写入文件 %s 时出错，在第 %d 行\n", filename, i + 1);
            fclose(file);  // 关闭文件
            exit(-1);
        }
    }

    fclose(file);
    printf("成功将数据写入文件 %s\n", filename);
}

void Load8uData(const char* filename, Ipp8u* data, int length)
{
    FILE* file;
    fopen_s(&file, filename, "r");
    if (!file) {
        printf("无法打开文件 %s\n", filename);
        exit(-1);
    }

    for (int i = 0; i < length; i++) {
        float real;
        // 修复 fscanf_s 的返回值判断，返回值应为 1
        if (fscanf_s(file, "%f", &real) != 1) {
            printf("读取文件 %s 时出错，在第 %d 行\n", filename, i + 1);
            fclose(file);  // 关闭文件
            exit(-1);
        }
        data[i] = real;  // 存储到数组
    }

    fclose(file);
    printf("成功加载文件 %s\n", filename);
}

void Load32uData(const char* filename, Ipp32u* data, int length)
{
    FILE* file;
    fopen_s(&file, filename, "r");
    if (!file) {
        printf("无法打开文件 %s\n", filename);
        exit(-1);
    }

    for (int i = 0; i < length; i++) {
        float real;
        // 修复 fscanf_s 的返回值判断，返回值应为 1
        if (fscanf_s(file, "%f", &real) != 1) {
            printf("读取文件 %s 时出错，在第 %d 行\n", filename, i + 1);
            fclose(file);  // 关闭文件
            exit(-1);
        }
        data[i] = real;  // 存储到数组
    }

    fclose(file);
    printf("成功加载文件 %s\n", filename);
}


void LoadCharData(const char* filename, char* data, int length)
{
    FILE* file;
    fopen_s(&file, filename, "r");
    if (!file) {
        printf("无法打开文件 %s\n", filename);
        exit(-1);
    }

    for (int i = 0; i < length; i++) {
        float real;
        if (fscanf_s(file, "%f", &real) != 1) {
            printf("读取文件 %s 时出错，在第 %d 行\n", filename, i + 1);
            fclose(file);
            exit(-1);
        }

        // **关键修改**: 转换为字符'0'/'1'而不是数值0/1
        if (real == 1.0f) {
            data[i] = '1';  // ASCII 49
        }
        else {
            data[i] = '0';  // ASCII 48
        }
    }

    fclose(file);
    printf("成功加载文件 %s\n", filename);
}


void channel_estimation_SBL(Ipp32fc* symbol_demo_parallel, Ipp32s bitnum_every_frame_encode, const Ipp32fc* symbol, int channel_length, int N_samp, int frame_num, int NFFT, Ipp32fc* H_LS_NFFT, Ipp32fc* channel_estimation_user1, Ipp32s va_N_samp_SIMO, Ipp32s va_N_g)
{
    Ipp32fc* x_NFFT = ippsMalloc_32fc((N_samp - channel_length + 1) * channel_length);  // 用于存储符号帧的矩阵
    Ipp32fc* Yp = ippsMalloc_32fc(N_samp - channel_length + 1);                    // 用于存储接收到的符号
    Ipp32fc* u_h = ippsMalloc_32fc(channel_length);                                // 用于存储信道估计结果
    Ipp32fc* fft_input = ippsMalloc_32fc(NFFT);
    Ipp32fc* fft_output = ippsMalloc_32fc(NFFT);// FFT 输入缓冲区
    Ipp32fc* symbol_frame = ippsMalloc_32fc(bitnum_every_frame_encode);          // Original symbol frame
    Ipp32fc* out_frac = ippsMalloc_32fc(bitnum_every_frame_encode); // 存储当前列的数据
    Ipp32fc* H_TEMP = ippsMalloc_32fc(frame_num * NFFT);
    ippsZero_32fc(H_TEMP, frame_num * NFFT);
    for (int ii = 0; ii < frame_num; ii++)
    {
        //提取帧中的符号
       //for (int row = 0; row < bitnum_every_frame_encode; row++) {
       //    out_frac[row] = symbol_demo_parallel[row * frame_num + ii]; // 获取第 row 行的第 ii 列
       //}
        ippsCopy_32fc(symbol_demo_parallel + ii * bitnum_every_frame_encode, out_frac, bitnum_every_frame_encode);

        ippsCopy_32fc(symbol + bitnum_every_frame_encode * ii, symbol_frame, bitnum_every_frame_encode);
        // 构造 X 矩阵
        for (int row = 0; row < channel_length; row++) {
            for (int col = 0; col < N_samp - channel_length + 1; col++) {
                x_NFFT[col * channel_length + row] = symbol_frame[col + channel_length - row - 1];
            }
        }
        // Yp 矩阵为接收的符号
        ippsCopy_32fc(out_frac + channel_length - 1, Yp, N_samp - channel_length + 1);
        // 使用 SBL 函数进行信道估计
        SBL(x_NFFT, Yp, N_samp - channel_length + 1, channel_length, 1, u_h, va_N_samp_SIMO, va_N_g);
        // 保存信道估计结果
        // 准备 FFT 输入（补零到 NFFT 长度）
        ippsZero_32fc(fft_input, NFFT);
        ippsCopy_32fc(u_h, fft_input, channel_length);
        ippsCopy_32fc(u_h, channel_estimation_user1 + ii * channel_length, channel_length);
        // FFT 变换
        Ipps_FFT_32fc_SC(fft_input, H_LS_NFFT + ii * NFFT, NFFT);
        Ipps_FFT_32fc_SC(fft_input, H_TEMP + ii * NFFT, NFFT);
    }



    ippsCopy_32fc(H_TEMP, H_LS_NFFT, frame_num * NFFT);
    // 释放内存
    ippsFree(x_NFFT);
    ippsFree(Yp);
    ippsFree(u_h);
    ippsFree(fft_input);
    ippsFree(fft_output);
    ippsFree(symbol_frame);
    ippsFree(out_frac);
    //ippsFree(H_TEMP);
}

void SplitBlocksAndSeparate(const Ipp32fc* DownSampledSig, Ipp32s FinalLength, Ipp32s N_block, Ipp32fc* UWParts, Ipp32fc* DataParts, Ipp32s va_N_g)
{
    Ipp32s BlockLength = FinalLength / N_block; // 每个块的长度
    Ipp32s DataLength = BlockLength - va_N_g;     // 数据部分长度

    // 遍历每个块并提取 UW 和数据部分
    for (Ipp32s blockIdx = 0; blockIdx < N_block; blockIdx++) {
        // UW 部分的起始索引和终止索引
        Ipp32s UWStartIdx = blockIdx * BlockLength;

        // 数据部分的起始索引
        Ipp32s DataStartIdx = UWStartIdx + va_N_g;

        // 将 UW 部分复制到 UWParts
        ippsCopy_32fc(DownSampledSig + UWStartIdx, UWParts + blockIdx * va_N_g, va_N_g);

        // 将数据部分复制到 DataParts
        ippsCopy_32fc(DownSampledSig + DataStartIdx, DataParts + blockIdx * DataLength, DataLength);
    }
}

void HardDecision(int length, Ipp32fc* DecisionSymbolSoft, Ipp32fc* Table, int TableSize, Ipp32fc* DecisionSymbol)
{
    // 分配存储距离的临时数组
    Ipp64f* Distance_all = ippsMalloc_64f(TableSize);

    for (int j = 0; j < length; ++j) {
        // 计算 DecisionSymbolSoft[j] 与调制表的所有距离
        for (int t = 0; t < TableSize; ++t) {
            Ipp32fc diff;
            ippsSub_32fc(&DecisionSymbolSoft[j], &Table[t], &diff, 1); // 计算差值
            ippsNorm_L2_32fc64f(&diff, 1, &Distance_all[t]);          // 计算 L2 范数
        }

        // 找到最小距离对应的索引
        double min_distance;
        int min_index;
        ippsMinIndx_64f(Distance_all, TableSize, &min_distance, &min_index);

        // 记录最小距离对应的调制符号
        DecisionSymbol[j] = Table[min_index];
    }

    // 释放临时数组
    ippsFree(Distance_all);
}

void HardDecision_64f(int length, Ipp64fc* DecisionSymbolSoft, Ipp64fc* Table, int TableSize, Ipp64fc* DecisionSymbol)
{
    // 分配存储距离的临时数组
    Ipp64f* Distance_all = ippsMalloc_64f(TableSize);

    for (int j = 0; j < length; ++j) {
        // 计算 DecisionSymbolSoft[j] 与调制表的所有距离
        for (int t = 0; t < TableSize; ++t) {
            Ipp64fc diff;
            ippsSub_64fc(&DecisionSymbolSoft[j], &Table[t], &diff, 1); // 计算差值
            ippsNorm_L2_64fc64f(&diff, 1, &Distance_all[t]);          // 计算 L2 范数
        }

        // 找到最小距离对应的索引
        double min_distance;
        int min_index;
        ippsMinIndx_64f(Distance_all, TableSize, &min_distance, &min_index);

        // 记录最小距离对应的调制符号
        DecisionSymbol[j] = Table[min_index];
    }

    // 释放临时数组
    ippsFree(Distance_all);
}

void DeinterleaveBits(const Ipp32u* Sort_Table, int tableLength, const Ipp8u* BitsAftDemaapping, Ipp8u* OutputBits)
{
    // 使用 Sort_Table 的索引对 BitsAftDemaapping 进行重新排列
    for (int i = 0; i < tableLength; i++) {
        int index = Sort_Table[i] - 1;
        OutputBits[index] = BitsAftDemaapping[i]; // 按照索引重排
    }
}

void MIMO_PTR_IPP_RealConv(const Ipp32fc* pChannelEstimation, int channel_num, int channel_len, const Ipp32fc* pOutFrac, int out_frac_length, Ipp32fc* pOutput_tr)
{
    // 1) 先清空输出
    ippsZero_32fc(pOutput_tr, out_frac_length);

    // 2) 为“实数卷积”准备缓冲区：同一对 (src1Len, src2Len) 多次调用可复用一个 buffer
    //    这里 src1Len = out_frac_length, src2Len = channel_len
    IppEnum algType = (IppEnum)(ippAlgFFT);  // 或者 ippAlgDirect / ippAlgFFT 等
    int bufSize = 0;
    ippsConvolveGetBufferSize(out_frac_length, channel_len, ipp32f, algType, &bufSize);
    Ipp8u* pBuffer = ippsMalloc_8u(bufSize); // 注意：用完要 free

    // 3) 逐通道累加
    for (int ch = 0; ch < channel_num; ch++)
    {
        // (A) 准备当前通道的“翻转+共轭”h
        std::vector<Ipp32f> hrFlip(channel_len), hiFlip(channel_len);
        {
            const Ipp32fc* pH = pChannelEstimation + ch * channel_len;
            for (int i = 0; i < channel_len; i++)
            {
                int idx_src = channel_len - 1 - i; // 翻转
                hrFlip[i] = pH[idx_src].re;       // 实部
                hiFlip[i] = -pH[idx_src].im;       // 虚部取负 (共轭)
            }
        }

        // (B) 拆分 out_frac(ch,:) 为实部 xRe / 虚部 xIm
        std::vector<Ipp32f> xRe(out_frac_length), xIm(out_frac_length);
        {
            const Ipp32fc* pX = pOutFrac + ch * out_frac_length;
            for (int i = 0; i < out_frac_length; i++)
            {
                xRe[i] = pX[i].re;
                xIm[i] = pX[i].im;
            }
        }

        // (C) 4 次实数卷积，组合出复数卷积
        int conv_len = out_frac_length + channel_len - 1;
        std::vector<Ipp32f> conv_re_re(conv_len), conv_im_im(conv_len);
        std::vector<Ipp32f> conv_re_im(conv_len), conv_im_re(conv_len);

        // yRe = conv(xRe, hrFlip) - conv(xIm, hiFlip)
        ippsConvolve_32f(xRe.data(), out_frac_length,
            hrFlip.data(), channel_len,
            conv_re_re.data(), algType, pBuffer);

        ippsConvolve_32f(xIm.data(), out_frac_length,
            hiFlip.data(), channel_len,
            conv_im_im.data(), algType, pBuffer);

        // yIm = conv(xRe, hiFlip) + conv(xIm, hrFlip)
        ippsConvolve_32f(xRe.data(), out_frac_length,
            hiFlip.data(), channel_len,
            conv_re_im.data(), algType, pBuffer);

        ippsConvolve_32f(xIm.data(), out_frac_length,
            hrFlip.data(), channel_len,
            conv_im_re.data(), algType, pBuffer);

        // 组合得到复数卷积结果 conv_out
        std::vector<Ipp32fc> conv_out(conv_len);
        for (int i = 0; i < conv_len; i++)
        {
            conv_out[i].re = conv_re_re[i] - conv_im_im[i]; // 实部
            conv_out[i].im = conv_re_im[i] + conv_im_re[i]; // 虚部
        }

        // (D) 取出 MATLAB 中符号区段：channel_len : channel_len-1+out_frac_length
        //     换算到 C++ 0-based: [channel_len - 1, ..., (channel_len - 1) + (out_frac_length - 1)]
        //     共 out_frac_length 个点
        for (int i = 0; i < out_frac_length; i++)
        {
            pOutput_tr[i].re += conv_out[channel_len - 1 + i].re;
            pOutput_tr[i].im += conv_out[channel_len - 1 + i].im;
        }
    }

    // 4) 释放临时缓冲区
    ippsFree(pBuffer);

    // 5) 若要归一化，可自行做，比如：output_tr = output_tr / max(abs(output_tr))
    //    （以下为可选示例）
    // Ipp32f maxAbs = 0.f;
    // ippsMaxAbs_32fc(pOutput_tr, out_frac_length, &maxAbs);
    // if (maxAbs > 1e-12f) {
    //     Ipp32fc divisor = { maxAbs, 0.f };
    //     ippsDivC_32fc_I(divisor, pOutput_tr, out_frac_length);
    // }
}

void BlockFDE_NP(Ipp32fc* SignalRecData, Ipp32fc* BinaryUWArray, Ipp32fc* H_LS_NFFT, int N_FFT, int L_CNT, int N_block, int N_g_Block_FDE_NP, float LinerSNR, Ipp32fc* Table, Ipp32fc* UW_RecArray, int block_num, Ipp32fc* IFI, Ipp32fc* SymbolTxMatrix, int N_samp, Ipp32fc* SignalbeforeHD, Ipp32s va_g_N_Block)
{
    // 分配内存
    Ipp32fc* Hls_2 = ippsMalloc_32fc(va_g_N_Block * N_FFT);
    Ipp32fc* b_mmse = ippsMalloc_32fc(va_g_N_Block * L_CNT);
    Ipp32fc* A_mmse_LM = ippsMalloc_32fc(va_g_N_Block * N_FFT);
    Ipp32fc* W_mmse = ippsMalloc_32fc(va_g_N_Block * N_FFT);
    Ipp32fc* SignalFD_DataRec = ippsMalloc_32fc(va_g_N_Block * N_FFT);
    Ipp32fc* SignalFD_DataEqu = ippsMalloc_32fc(va_g_N_Block * N_FFT);
    Ipp32fc* Signal_DataEqu = ippsMalloc_32fc(va_g_N_Block * N_FFT);
    Ipp32fc* g_FB = ippsMalloc_32fc(L_CNT * va_g_N_Block);
    Ipp32fc* SignalAfterDFE = ippsMalloc_32fc(va_g_N_Block * (N_FFT - N_g_Block_FDE_NP));

    // 1. 计算 Hls_2 = 1/(H_LS_NFFT * conj(H_LS_NFFT) + 1/LinerSNR)
    for (int i = 0; i < N_block * N_FFT; i++) {
        Ipp32fc h_conj = { H_LS_NFFT[i].re, -H_LS_NFFT[i].im };
        float denom = H_LS_NFFT[i].re * H_LS_NFFT[i].re +
            H_LS_NFFT[i].im * H_LS_NFFT[i].im + 1.0f / LinerSNR;
        Hls_2[i].re = 1.0f / denom;
        Hls_2[i].im = 0;
    }

    // 2. 计算反馈系数 g_FB
    // FFT变换以计算 b_mmse
    for (int block = 0; block < N_block; block++) {
        Ipps_FFT_32fc_SC(Hls_2 + block * N_FFT, A_mmse_LM + block * N_FFT, N_FFT);
        // 提取前 L_CNT 个系数
        ippsCopy_32fc(A_mmse_LM + block * N_FFT + 1, b_mmse + block * L_CNT, L_CNT);
    }
    for (int i = 0; i < N_block * L_CNT; i++)
    {
        b_mmse[i].im = -b_mmse[i].im;
    }

    // 3. 构建 Toeplitz 矩阵并求解反馈系数
    for (int block = 0; block < N_block; block++) {
        // 分配并构建 Toeplitz 矩阵
        Ipp32fc* A_toeplitz = ippsMalloc_32fc(L_CNT * L_CNT);
        BuildToeplitzMatrix(A_mmse_LM + block * N_FFT, L_CNT, A_toeplitz);

        // 求解线性方程组 A_toeplitz * g_FB = b_mmse
        SolveLinearEquation(A_toeplitz, b_mmse + block * L_CNT, L_CNT, g_FB + block * L_CNT);

        ippsFree(A_toeplitz);
    }

    // 4. 计算前馈系数 W_mmse
    for (int i = 0; i < N_block * N_FFT; i++) {
        Ipp32fc h_conj = { H_LS_NFFT[i].re, -H_LS_NFFT[i].im };
        float denom = H_LS_NFFT[i].re * H_LS_NFFT[i].re +
            H_LS_NFFT[i].im * H_LS_NFFT[i].im + 1.0f / LinerSNR;
        W_mmse[i].re = h_conj.re / denom;
        W_mmse[i].im = h_conj.im / denom;
    }

    // 5. 前馈均衡
    // FFT变换接收信号
    for (int block = 0; block < N_block; block++) {
        Ipps_FFT_32fc_SC(SignalRecData + block * N_FFT, SignalFD_DataRec + block * N_FFT, N_FFT);
        // 减去帧间干扰
        ippsSub_32fc(IFI + block * N_FFT, SignalFD_DataRec + block * N_FFT,
            SignalFD_DataRec + block * N_FFT, N_FFT);
        // 前馈均衡
        ippsMul_32fc(W_mmse + block * N_FFT, SignalFD_DataRec + block * N_FFT,
            SignalFD_DataEqu + block * N_FFT, N_FFT);
        // IFFT
        Ipps_IFFT_32fc_SC(SignalFD_DataEqu + block * N_FFT, Signal_DataEqu + block * N_FFT, N_FFT);
    }

    // 6. 分组相位校正
    // 提取非UW部分
    Ipp32fc* Signal_DataEqu_NoUW = ippsMalloc_32fc(N_block * (N_FFT - N_g_Block_FDE_NP));
    for (int block = 0; block < N_block; block++) {
        ippsCopy_32fc(Signal_DataEqu + block * N_FFT,
            Signal_DataEqu_NoUW + block * (N_FFT - N_g_Block_FDE_NP), N_FFT - N_g_Block_FDE_NP);
    }

    // 调用相位校正函数
    Ipp32f* phi = ippsMalloc_32f(phi_size);
    GroupPhaseCorrection(Signal_DataEqu_NoUW, N_block, N_FFT - N_g_Block_FDE_NP, N_samp,
        SymbolTxMatrix, Table, 4, block_num, Signal_DataEqu_NoUW, phi);
    ippsFree(phi);


    ippsSub_32fc(BinaryUWArray, UW_RecArray, UW_RecArray, N_g_Block_FDE_NP);
    ippsCopy_32fc(UW_RecArray, Signal_DataEqu, N_g_Block_FDE_NP);

    ippsCopy_32fc(Signal_DataEqu_NoUW, Signal_DataEqu + N_g_Block_FDE_NP, N_FFT - N_g_Block_FDE_NP);


    // 7. 反馈均衡
    for (int block = 0; block < N_block; block++) {
        int uw_len = N_g_Block_FDE_NP;
        for (int i = uw_len; i < N_FFT; i++) {
            Ipp32fc dfe_value = { 0, 0 };
            Ipp32fc dfe_sum = { 0, 0 };
            // 计算反馈项
            for (int j = 0; j < L_CNT; j++) {
                int idx = i - L_CNT + j;
                Ipp32fc val11 = g_FB[block * L_CNT + L_CNT - j - 1];
                Ipp32fc val22 = Signal_DataEqu[block * N_FFT + idx];
                if (idx >= 0) {
                    ippsMul_32fc(&Signal_DataEqu[block * N_FFT + idx],
                        &g_FB[block * L_CNT + L_CNT - j - 1],
                        &dfe_value, 1);
                    dfe_sum.re += dfe_value.re;
                    dfe_sum.im += dfe_value.im;
                }
            }

            // 减去反馈项得到均衡后的信号
            ippsSub_32fc(&dfe_sum, &Signal_DataEqu[block * N_FFT + i],
                &SignalAfterDFE[block * (N_FFT - uw_len) + (i - uw_len)], 1);

            // 保存未经硬判决的信号
            SignalbeforeHD[block * (N_FFT - uw_len) + (i - uw_len)] =
                SignalAfterDFE[block * (N_FFT - uw_len) + (i - uw_len)];

            // 硬判决
            if (i < N_FFT) {
                HardDecision(1,
                    &SignalAfterDFE[block * (N_FFT - uw_len) + (i - uw_len)],
                    Table, 4,
                    &SignalAfterDFE[block * (N_FFT - uw_len) + (i - uw_len)]);
            }

            // 更新用于下一次迭代的信号
            ippsSub_32fc(&SignalAfterDFE[block * (N_FFT - uw_len) + (i - uw_len)],
                &Signal_DataEqu[block * N_FFT + i],
                &Signal_DataEqu[block * N_FFT + i], 1);
        }
    }

    // 释放内存
    ippsFree(Hls_2);
    ippsFree(b_mmse);
    ippsFree(A_mmse_LM);
    ippsFree(W_mmse);
    ippsFree(SignalFD_DataRec);
    ippsFree(SignalFD_DataEqu);
    ippsFree(Signal_DataEqu);
    ippsFree(g_FB);
    ippsFree(SignalAfterDFE);
    ippsFree(Signal_DataEqu_NoUW);
}

void BuildToeplitzMatrix(const Ipp32fc* input, int size, Ipp32fc* output)
{
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            int idx = std::abs(i - j); // Toeplitz 特性：元素只与下标差有关
            if (i <= j) {
                // 下三角，共轭对称
                output[i * size + j] = input[idx];
            }
            else {
                // 上三角，直接取值
                output[i * size + j].re = input[idx].re;
                output[i * size + j].im = -input[idx].im; // 虚部取负
            }
        }
    }
}

void SolveLinearEquation(const Ipp32fc* A, const Ipp32fc* b, int n, Ipp32fc* x)
{
    MKL_Complex8* A_mkl = (MKL_Complex8*)mkl_malloc(n * n * sizeof(MKL_Complex8), 64);
    MKL_Complex8* b_mkl = (MKL_Complex8*)mkl_malloc(n * sizeof(MKL_Complex8), 64);

    for (int i = 0; i < n * n; i++) {
        A_mkl[i].real = A[i].re;
        A_mkl[i].imag = A[i].im;
    }
    for (int i = 0; i < n; i++) {
        b_mkl[i].real = b[i].re;
        b_mkl[i].imag = b[i].im;
    }

    // 分配工作空间
    int* ipiv = (int*)mkl_malloc(n * sizeof(int), 64);

    // 求解线性方程组
    int info = LAPACKE_cgesv(LAPACK_ROW_MAJOR, n, 1, A_mkl, n, ipiv, b_mkl, 1);

    // 将结果转换回 IPP 复数
    for (int i = 0; i < n; i++) {
        x[i].re = b_mkl[i].real;
        x[i].im = b_mkl[i].imag;
    }

    // 释放内存
    mkl_free(A_mkl);
    mkl_free(b_mkl);
    mkl_free(ipiv);
}

void MIMO_syn_dopl_baseband(int channel_num, int N_block, Ipp32f* SignalAftNoise, Ipp32fc* UWParts, Ipp32fc* DataParts, Ipp32s va_g_f0, Ipp32s va_g_fs, Ipp32s va_N_upsample, Ipp32s va_N_g)
{
    Ipp32fc* UWParts_temp = ippsMalloc_32fc(N_block * N_g);
    Ipp32fc* DataParts_temp = ippsMalloc_32fc(N_block * g_Syn_NFFT);
    for (int i = 0; i < channel_num; i++)
    {
        //带通滤波，对SignalAftNoise进行带通滤波
        Ipp32f* SignalAftBP = ippsMalloc_32f(Signal_After_BP_lenth);
        DownConversion_BandPass(SignalAftNoise + i * Signal_After_BP_lenth, Signal_After_BP_lenth,
            Syn_FIRCoe_SC_BANDPASS, Syn_FIRLen_BANDPASS,
            SignalAftBP);
        //同步，对信号进行同步
        Ipp32f* Syn_SigRec = ippsMalloc_32f(g_InfoSamPointTotalSyn);
        Ipp32s* Syn_PosSecond = ippsMalloc_32s(1);


        Ipp32f* Syn_RefCopyAll_Real = ippsMalloc_32f(g_LFM2Data_lenth);


        for (int i = 0; i < g_LFM2Data_lenth; i++)
        {
            Syn_RefCopyAll_Real[i] = Syn_RefCopyAll[i].re;
        }


        Sync_SC(SignalAftBP, Syn_RefCopyAll_Real,
            Syn_PosSecond, Syn_SigRec);








        //IQ解调 + 根升余弦滤波器 + 降采样 + 去掉 UW 前缀
        Ipp32fc* DownSampledSig = ippsMalloc_32fc(((g_InfoSamPointTotalSyn - 96) / N_upsample) - N_g);
        DownConversion_SC(Syn_SigRec, g_InfoSamPointTotalSyn, Syn_FIRCoe_SC, Syn_FIRLen,
            DownSampledSig, va_g_f0, va_g_fs, va_N_upsample, va_N_g);


        //分块，分为FFT块还有数据块
        SplitBlocksAndSeparate(DownSampledSig, ((g_InfoSamPointTotalSyn - 96) / N_upsample) - N_g, N_block, UWParts_temp, DataParts_temp, N_g);
        ippsCopy_32fc(UWParts_temp, UWParts + i * N_block * N_g, N_block * N_g);
        ippsCopy_32fc(DataParts_temp, DataParts + i * N_block * g_Syn_NFFT, N_block * g_Syn_NFFT);



        ippsFree(SignalAftBP);
        ippsFree(Syn_SigRec);
        ippsFree(Syn_PosSecond);
        ippsFree(DownSampledSig);

    }
    ippsFree(UWParts_temp);
    ippsFree(DataParts_temp);
}

void GetBlockTemp(int Bcnt, int channel_num, int N_block, Ipp32fc* DataParts, Ipp32fc* Block_temp, Ipp32s va_g_Syn_NFFT)
{
    // 遍历每个通道，提取对应块的内容
    for (int ch = 0; ch < channel_num; ch++) {
        // 计算 DataParts 中的起始索引
        int start_index = ch * N_block * va_g_Syn_NFFT + Bcnt * va_g_Syn_NFFT;

        // 计算 Block_temp 中的起始索引
        int temp_index = ch * va_g_Syn_NFFT;
        // 将数据复制到 Block_temp 的对应部分
        ippsCopy_32fc(DataParts + start_index, Block_temp + temp_index, va_g_Syn_NFFT);
    }
}

void MIMO_Mul_Process(int channel_num, int N_block, Ipp32fc* BinaryUWArray, Ipp32fc* Symbol, Ipp32fc* SymbolTxMatrix, Ipp32fc* DataParts, Ipp32fc* UWParts, Ipp32fc* Signal_DataEqu, Ipp32fc* h_Estimation, Ipp32s va_g_Syn_NFFT, Ipp32s va_N_g, Ipp32s va_N_samp_SIMO, Ipp32s va_g_block_num)
{
    for (int i = 0; i < N_block; i++)
    {
        Ipp32fc* Block_temp = ippsMalloc_32fc(channel_num * va_g_Syn_NFFT);
        Ipp32fc* Symbol_temp = ippsMalloc_32fc(N_block * va_g_Syn_NFFT);
        Ipp32fc* H_LS_NFFT = ippsMalloc_32fc(channel_num * va_g_Syn_NFFT);
        //Ipp32fc* h_Estimation = ippsMalloc_32fc(channel_num * N_g);
        Ipp32fc* q = ippsMalloc_32fc(va_N_g);
        Ipp32fc* q_FD = ippsMalloc_32fc(va_g_Syn_NFFT);
        Ipp32fc* symbol_user_ptr = ippsMalloc_32fc(va_g_Syn_NFFT);
        GetBlockTemp(i, channel_num, N_block, DataParts, Block_temp, va_g_Syn_NFFT);
        ippsCopy_32fc(Symbol + i * va_g_Syn_NFFT, Symbol_temp, va_g_Syn_NFFT);
        for (int ChannelCnt = 0; ChannelCnt < channel_num; ChannelCnt++)
        {
            channel_estimation_SBL(Block_temp + ChannelCnt * va_g_Syn_NFFT, va_g_Syn_NFFT,
                Symbol_temp, va_N_g, va_N_samp_SIMO, 1, va_g_Syn_NFFT,
                H_LS_NFFT + ChannelCnt * va_g_Syn_NFFT,
                h_Estimation + ChannelCnt * va_N_g,
                va_N_samp_SIMO, va_N_g);
        }
        MIMO_PTR_IPP_RealConv(h_Estimation, channel_num, va_N_g, Block_temp, va_g_Syn_NFFT, symbol_user_ptr);
        channel_estimation_SBL(symbol_user_ptr, va_g_Syn_NFFT, Symbol_temp, va_N_g, va_N_samp_SIMO, 1, va_g_Syn_NFFT, q_FD, q, va_N_samp_SIMO, va_N_g);
        Ipp32fc* IFI = ippsMalloc_32fc(va_g_Syn_NFFT);
        ippsZero_32fc(IFI, va_g_Syn_NFFT);
        float SNR_SIMO = SNR_CONST;
        BlockFDE_NP(
            symbol_user_ptr,
            BinaryUWArray + i * va_N_g,
            q_FD,
            va_g_Syn_NFFT,
            va_N_g,
            1,
            va_N_g,
            SNR_SIMO,
            Table,
            UWParts + i * va_N_g,
            va_g_block_num,
            IFI,
            SymbolTxMatrix + i * (va_g_Syn_NFFT - va_N_g),
            va_N_samp_SIMO,
            Signal_DataEqu + i * (va_g_Syn_NFFT - va_N_g),
            N_block
        );
        ippsCopy_32fc(SymbolTxMatrix + i * (va_g_Syn_NFFT - va_N_g), Signal_DataEqu + i * (va_g_Syn_NFFT - va_N_g), va_N_samp_SIMO);
        ippsZero_32fc(h_Estimation, channel_num * va_N_g);


    }
}

void ViterbiDecode(const char* encoded_bits, int constraint, int poly1, int poly2, char* output_buffer, int buffer_size)
{
    std::vector<int> polynomials;
    polynomials.push_back(poly1);   // octal 133
    polynomials.push_back(poly2);  // octal 171，对应802.11标准
    ViterbiCodec codec(constraint, polynomials);
    std::string decoded = codec.Decode(std::string(encoded_bits));

    // 使用 strncpy_s 来安全地复制字符串
    strncpy_s(output_buffer, buffer_size, decoded.c_str(), buffer_size - 1);  // 保证不会超出缓冲区大小
    output_buffer[buffer_size - 1] = '\0';  // 确保字符串以 NULL 结尾
}

void Mapping(const Ipp8u* InputBit, int LenInput, int M, Ipp32fc* Output, const Ipp32fc* TableMod)
{
    int Q = static_cast<int>(std::log2(M));  // 每个符号的比特数
    int LenSymbols = LenInput / Q;  // 符号数
    int* DecadeSeq = new int[LenSymbols];  // 存储每个符号的十进制值

    // 将输入比特流按调制方式划分成符号
    for (int i = 0; i < LenSymbols; i++) {
        DecadeSeq[i] = 0;
        for (int j = 0; j < Q; j++) {
            DecadeSeq[i] += (InputBit[i * Q + j] << j);
        }
    }

    // 根据传入的调制符号表生成对应的星座图符号
    for (int i = 0; i < LenSymbols; i++) {
        Output[i] = TableMod[DecadeSeq[i]];  // 使用映射表将十进制符号映射到星座图符号
    }

    delete[] DecadeSeq;
}

void BlockCreat(const Ipp32fc* SymbolIn, const int SymbolIn_Len, const Ipp32fc* BinaryUW, const int BinaryUW_Len, int N_block, Ipp32fc* SymbolInSend)
{
    int LenBinarySendArray = N_block * (SymbolIn_Len / N_block + 2 * BinaryUW_Len);  // 计算 BinarySendArray 的长度
    // 重新排列 SymbolIn 成 SymbolInDataArray
    Ipp32fc* SymbolInDataArray = ippsMalloc_32fc(SymbolIn_Len);
    ippsCopy_32fc(SymbolIn, SymbolInDataArray, SymbolIn_Len);
    Ipp32fc* BinarySendArray = ippsMalloc_32fc(LenBinarySendArray);
    // 构造 BinarySendArray
    for (int i = 0; i < N_block; i++) {
        // 将 BinaryUW 和 SymbolInDataArray 按顺序合并
        ippsCopy_32fc(BinaryUW, BinarySendArray + i * (SymbolIn_Len / N_block + BinaryUW_Len * 2), BinaryUW_Len);
        ippsCopy_32fc(SymbolIn + i * (SymbolIn_Len / N_block), BinarySendArray + i * (SymbolIn_Len / N_block + BinaryUW_Len * 2) + BinaryUW_Len, SymbolIn_Len / N_block);
        ippsCopy_32fc(BinaryUW, BinarySendArray + (i + 1) * (SymbolIn_Len / N_block + BinaryUW_Len * 2) - BinaryUW_Len, BinaryUW_Len);
    }
    // 拼接最后的 UW 到 SymbolInSend
    ippsCopy_32fc(BinaryUW, SymbolInSend, BinaryUW_Len);
    ippsCopy_32fc(BinarySendArray, SymbolInSend + BinaryUW_Len, LenBinarySendArray);
    ippsFree(SymbolInDataArray);
    ippsFree(BinarySendArray);
}

void InterleaveBits(const Ipp32u* Sort_Table, int tableLength, const char* InputBits, Ipp8u* OutputBits)
{
    // 对每个索引按照 Sort_Table 进行数据重排：将 InputBits 中位置 Sort_Table[i]-1 的数据放到 OutputBits[i] 中
    for (int i = 0; i < tableLength; i++) {
        int index = Sort_Table[i] - 1;  // 因为 Sort_Table 中的值是从 1 开始，所以需要减 1
        OutputBits[i] = static_cast<Ipp8u>(InputBits[index] - '0'); // 将字符 '0' 或 '1' 转换为数字 0 或 1
    }
}

void UpsampleSignal(const Ipp32fc* InputSignal, int InputSignalLen, int Nsamp, Ipp32fc* UpsamSignal, int UpsamSignal_Len, Ipp32fc* Syn_FIR, Ipp32s FIRLen)
{
    // InputSignal: 输入信号
    // InputSignalLen: 输入信号的长度
    // Nsamp: 升采样因子
    // UpsamSignal: 输出升采样后的信号

    // 计算升采样后信号的长度
    int UpsamSignalLen = InputSignalLen * Nsamp;
    Ipp32fc* UpsamSignal_temp = ippsMalloc_32fc(UpsamSignal_Len);
    // 将输入信号的每个元素插入到升采样信号中
    for (int i = 0; i < InputSignalLen; ++i) {
        UpsamSignal_temp[i * Nsamp] = InputSignal[i];  // 每隔 Nsamp 个位置插入一个输入信号的元素
    }
    SC_FIR(UpsamSignal_temp, UpsamSignal_Len, Syn_FIR, FIRLen, UpsamSignal); // FIR 滤波，这个测试了没问题
    //ippsFree(Delay);
    ippsFree(UpsamSignal_temp);
}

void Save32fData(const char* filename, Ipp32f* data, int length)
{
    FILE* file;
    fopen_s(&file, filename, "w");
    if (!file) {
        printf("无法打开文件 %s\n", filename);
        exit(-1);
    }

    for (int i = 0; i < length; i++) {
        // 将数据写入文件，每行一个数值
        if (fprintf(file, "%f\n", data[i]) < 0) {
            printf("写入文件 %s 时出错，在第 %d 行\n", filename, i + 1);
            fclose(file);  // 关闭文件
            exit(-1);
        }
    }

    fclose(file);
    printf("成功将数据写入文件 %s\n", filename);
}

void DownConversion_SC_PSK(Ipp32f* Syn_SigIn, Ipp32s Syn_SigLen, Ipp32fc* Syn_FIRCoe, Ipp32s Syn_FIRLen, Ipp32fc* DownSampledSig)
{
    //申请内存
    Ipp32u SigCnt = 0, delay = 0;
    Ipp32fc* MixSig = ippsMalloc_32fc(Syn_SigLen + Syn_FIRLen - 1);
    Ipp32fc* MixSigFIR = ippsMalloc_32fc(Syn_SigLen + Syn_FIRLen - 1);
    ippsZero_32fc(MixSig, Syn_SigLen + Syn_FIRLen - 1);
    ippsZero_32fc(MixSigFIR, Syn_SigLen + Syn_FIRLen - 1);

    /// Section 1: 调制到基带
    Ipp32f* VectorInt = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* SinVectorInt = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* CosVectorInt = ippsMalloc_32f(Syn_SigLen);

    Ipp32f* SigSin = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* SigCos = ippsMalloc_32f(Syn_SigLen);

    for (SigCnt = 0; SigCnt < Syn_SigLen; SigCnt++)
    {
        *(VectorInt + SigCnt) = (Ipp32f)(-2 * IPP_PI * g_f0 * SigCnt / g_fs);
    }
    //生成正弦和余弦
    ippsSin_32f_A11(VectorInt, SinVectorInt, Syn_SigLen);
    ippsMul_32f(Syn_SigIn, SinVectorInt, SigSin, Syn_SigLen);
    ippsCos_32f_A11(VectorInt, CosVectorInt, Syn_SigLen);
    ippsMul_32f(Syn_SigIn, CosVectorInt, SigCos, Syn_SigLen);

    //组合成复数信号
    ippsRealToCplx_32f(SigCos, SigSin, MixSig, Syn_SigLen);




    Ipp32fc* filteredSignal = (Ipp32fc*)ippsMalloc_32fc(Syn_SigLen); // 分配内存用于存储滤波结果

    SC_FIR(MixSig, Syn_SigLen, Syn_FIRCoe, Syn_FIRLen, filteredSignal); // FIR 滤波，这个测试了没问题

    Ipp32fc* OutputSignal = (Ipp32fc*)ippsMalloc_32fc(Syn_SigLen);   // 分配内存用于最终输出

    delay = (Syn_FIRLen - 1) / 2; // 等效于 fix(length(PulseShape)/2)
    ippsCopy_32fc(filteredSignal + delay, OutputSignal, Syn_SigLen - delay); // 裁剪延迟




    /// Section 2: 实现降采样
    Ipp32s LengthOutSignal = Syn_SigLen - delay;      // 滤波后的信号长度
    Ipp32s LengthAftDown = LengthOutSignal / N_upsample; // 降采样后的信号长度
    Ipp32fc* TempDownSampledSig = ippsMalloc_32fc(LengthAftDown);

    for (Ipp32s i = 0; i < LengthAftDown && i * N_upsample < LengthOutSignal; i++) {
        TempDownSampledSig[i].re = 2 * OutputSignal[i * N_upsample].re; // 实部乘以 2
        TempDownSampledSig[i].im = 2 * OutputSignal[i * N_upsample].im; // 虚部乘以 2
    }
    //释放内存
    ippsFree(MixSig);
    ippsFree(MixSigFIR);
    ippsFree(VectorInt);
    ippsFree(SinVectorInt);
    ippsFree(CosVectorInt);
    ippsFree(SigSin);
    ippsFree(SigCos);
    ippsFree(TempDownSampledSig);
}

void FractionalSpacedEqualizer(Ipp32fc* SignalAftDownSam, int SignalAftDownSam_length, Ipp32fc* SymbolIn, int SymbolIn_length, int NumTrainBit, int NumTotalBit, int Q, Ipp32fc* Table, int TableSize, Ipp32fc* SignalAftW)
{
    int L1 = 80;                // 前馈滤波器抽头数
    int L2 = 120;               // 反馈滤波器抽头数
    float Delta = 0.5f;         // 相关矩阵初始化参数
    float Lambda = 0.9965f;     // 遗忘因子
    float PLL1 = 0.00001f;      // 锁相环参数1
    float PLL2 = 0.000001f;     // 锁相环参数2
    // 初始化权重向量，相关矩阵和其他缓冲区
    Ipp32fc* w = ippsMalloc_32fc(L1 + L2);
    ippsZero_32fc(w, L1 + L2);

    Ipp32fc* SignalAftDownSam_temp = ippsMalloc_32fc(SignalAftDownSam_length);
    ippsZero_32fc(SignalAftDownSam_temp, SignalAftDownSam_length);


    // 初始化相关矩阵 p (对角矩阵 Delta * I)
    Ipp32fc* p = ippsMalloc_32fc((L1 + L2) * (L1 + L2));
    ippsZero_32fc(p, (L1 + L2) * (L1 + L2));
    for (int i = 0; i < L1 + L2; i++) {
        p[i * (L1 + L2) + i].re = Delta;
        p[i * (L1 + L2) + i].im = 0.0f;
    }

    // 初始化误差和锁相环相关缓冲区
    Ipp32fc* Error = ippsMalloc_32fc(NumTotalBit / Q);
    ippsZero_32fc(Error, NumTotalBit / Q);

    Ipp32f* NCO_Phase = ippsMalloc_32f(NumTotalBit / Q);
    ippsZero_32f(NCO_Phase, NumTotalBit / Q);

    Ipp32f* Discriminator_Out = ippsMalloc_32f(NumTotalBit / Q);
    ippsZero_32f(Discriminator_Out, NumTotalBit / Q);

    Ipp32fc* daiding = ippsMalloc_32fc(NumTotalBit / Q);
    ippsZero_32fc(daiding, NumTotalBit / Q);

    Ipp32fc* temp = ippsMalloc_32fc(NumTotalBit / Q);
    ippsZero_32fc(temp, NumTotalBit / Q);

    Ipp32fc* decision = ippsMalloc_32fc(NumTotalBit / Q);
    ippsZero_32fc(decision, NumTotalBit / Q);

    // 初始化SignalAftW
    ippsZero_32fc(SignalAftW, NumTotalBit / Q);

    // 训练模式 - 使用已知训练序列
    for (int i = 2 * L2; i < 2 * NumTrainBit / Q; i++) {
        Ipp32fc* w1 = w;                 // 前馈滤波器权重
        Ipp32fc* w2 = w + L1;            // 反馈滤波器权重
        int num = i / 2;                 // 当前符号索引

        // 提取当前输入向量y并应用NCO相位校正
        Ipp32fc* y = ippsMalloc_32fc(L1);
        for (int j = 0; j < L1; j++) {
            int idx = i + L1 - j - 1;
            if (idx < SignalAftDownSam_length) {
                float phase = (num > 0) ? fmod(NCO_Phase[num - 1], 2 * IPP_PI) : 0;
                Ipp32fc phase_rotation = { cos(-phase), sin(-phase) };
                ippsCopy_32fc(SignalAftDownSam, SignalAftDownSam_temp, SignalAftDownSam_length);
                ippsMul_32fc_I(&phase_rotation, &SignalAftDownSam_temp[idx], 1);
                y[j] = SignalAftDownSam_temp[idx];
                ippsZero_32fc(SignalAftDownSam_temp, SignalAftDownSam_length);
            }
            else {
                y[j].re = 0.0f;
                y[j].im = 0.0f;
            }
        }

        // 计算前馈滤波器输出 pn
        Ipp32fc pn = { 0, 0 };
        ippsDotProd_32fc(w1, y, L1, &pn);

        if ((i + 1) % 2 == 0) {  // 每2个采样点处理一次，实现分数间隔
            // 提取反馈滤波器输入向量
            Ipp32fc* y_back = ippsMalloc_32fc(L2);
            for (int j = 0; j < L2; j++) {
                int idx = num - 1 - j;
                if (idx >= 0 && idx < SymbolIn_length) {
                    y_back[j] = SymbolIn[idx];
                }
                else {
                    y_back[j].re = 0.0f;
                    y_back[j].im = 0.0f;
                }
            }

            // 计算反馈滤波器输出 qn
            Ipp32fc qn = { 0, 0 };
            ippsDotProd_32fc(w2, y_back, L2, &qn);

            // 合并输入向量为u = [y; y_back]
            Ipp32fc* u = ippsMalloc_32fc(L1 + L2);
            ippsCopy_32fc(y, u, L1);
            ippsCopy_32fc(y_back, u + L1, L2);

            // 计算均衡器输出和误差
            SignalAftW[num] = { pn.re + qn.re, pn.im + qn.im };
            if (num < SymbolIn_length) {
                Error[num].re = SymbolIn[num].re - SignalAftW[num].re;
                Error[num].im = SymbolIn[num].im - SignalAftW[num].im;
            }

            // 更新权重和相关矩阵 (RLS算法)
            Ipp32fc* aa = ippsMalloc_32fc(L1 + L2);
            ippsZero_32fc(aa, L1 + L2);

            // 计算 aa = p * u
            for (int row = 0; row < L1 + L2; row++) {
                Ipp32fc sum = { 0, 0 };
                for (int col = 0; col < L1 + L2; col++) {
                    Ipp32fc product;
                    ippsMul_32fc(&p[row * (L1 + L2) + col], &u[col], &product, 1);
                    sum.re += product.re;
                    sum.im += product.im;
                }
                aa[row] = sum;
            }

            // 计算 bb = Lambda + u' * aa
            Ipp32fc bb = { Lambda, 0 };
            Ipp32fc u_h_aa;
            for (int j = 0; j < L1 + L2; j++) {
                Ipp32fc u_conj = { u[j].re, -u[j].im };
                Ipp32fc product;
                ippsMul_32fc(&u_conj, &aa[j], &product, 1);
                bb.re += product.re;
                bb.im += product.im;
            }

            // 计算 k = aa / bb
            Ipp32fc* k = ippsMalloc_32fc(L1 + L2);
            for (int j = 0; j < L1 + L2; j++) {
                Ipp32fc divisor = {
                    (bb.re * aa[j].re + bb.im * aa[j].im) / (bb.re * bb.re + bb.im * bb.im),
                    (bb.re * aa[j].im - bb.im * aa[j].re) / (bb.re * bb.re + bb.im * bb.im)
                };
                k[j] = divisor;
            }

            // 更新相关矩阵 p = (p - k * u' * p) / Lambda
            Ipp32fc* primer = ippsMalloc_32fc((L1 + L2) * (L1 + L2));
            ippsZero_32fc(primer, (L1 + L2) * (L1 + L2));

            // 计算 primer = k * u' * p
            for (int row = 0; row < L1 + L2; row++) {
                for (int col = 0; col < L1 + L2; col++) {
                    Ipp32fc sum = { 0, 0 };
                    for (int j = 0; j < L1 + L2; j++) {
                        Ipp32fc u_conj = { u[j].re, -u[j].im };
                        Ipp32fc temp1, temp2;
                        ippsMul_32fc(&k[row], &u_conj, &temp1, 1);
                        ippsMul_32fc(&temp1, &p[j * (L1 + L2) + col], &temp2, 1);
                        sum.re += temp2.re;
                        sum.im += temp2.im;
                    }
                    primer[row * (L1 + L2) + col] = sum;
                }
            }

            // 计算 p = (p - primer) / Lambda
            for (int j = 0; j < (L1 + L2) * (L1 + L2); j++) {
                p[j].re = (p[j].re - primer[j].re) / Lambda;
                p[j].im = (p[j].im - primer[j].im) / Lambda;
            }

            // 计算鉴相器输出
            Ipp32fc pn_conj = { pn.re, -pn.im };
            Ipp32fc error_plus_pn = { Error[num].re + pn.re, Error[num].im + pn.im };
            Ipp32fc discr_complex;
            ippsMul_32fc(&pn_conj, &error_plus_pn, &discr_complex, 1);
            Discriminator_Out[num] = discr_complex.im;

            // 更新NCO相位
            if (num >= 2) {
                NCO_Phase[num] = 2 * NCO_Phase[num - 1] - NCO_Phase[num - 2] +
                    PLL1 * Discriminator_Out[num] - PLL2 * Discriminator_Out[num - 1];
            }

            // 更新权重 w = w + k * Error[num]'  (注意：MATLAB中的'表示共轭转置)
            for (int j = 0; j < L1 + L2; j++) {
                // 计算Error[num]的共轭
                Ipp32fc error_conj = { Error[num].re, -Error[num].im };

                Ipp32fc product;
                ippsMul_32fc(&k[j], &error_conj, &product, 1);
                w[j].re += product.re;
                w[j].im += product.im;

            }
            // 释放临时内存
            ippsFree(y_back);
            ippsFree(u);
            ippsFree(aa);
            ippsFree(k);
            ippsFree(primer);
        }
        ippsFree(y);
    }

    // 决策引导模式 - 使用硬判决符号
    for (int i = 2 * NumTrainBit / Q + 1; i < 2 * NumTotalBit / Q - 2 * L1 + 1; i++) {
        Ipp32fc* w1 = w;                 // 前馈滤波器权重
        Ipp32fc* w2 = w + L1;            // 反馈滤波器权重
        int num = i / 2;                 // 当前符号索引

        // 提取当前输入向量y并应用NCO相位校正
        Ipp32fc* y = ippsMalloc_32fc(L1);
        for (int j = 0; j < L1; j++) {
            int idx = i + L1 - 1 - j;
            if (idx < SignalAftDownSam_length) {
                float phase = (num > 0) ? fmod(NCO_Phase[num - 1], 2 * IPP_PI) : 0;
                Ipp32fc phase_rotation = { cos(-phase), sin(-phase) };


                ippsCopy_32fc(SignalAftDownSam, SignalAftDownSam_temp, SignalAftDownSam_length);
                ippsMul_32fc_I(&phase_rotation, &SignalAftDownSam_temp[idx], 1);
                y[j] = SignalAftDownSam_temp[idx];
                ippsZero_32fc(SignalAftDownSam_temp, SignalAftDownSam_length);


            }
            else {
                y[j].re = 0.0f;
                y[j].im = 0.0f;
            }
        }

        if (i % 2 == 0) {  // 每2个采样点处理一次，实现分数间隔
            // 计算前馈滤波器输出 pn
            Ipp32fc pn = { 0, 0 };
            ippsDotProd_32fc(w1, y, L1, &pn);
            // 提取反馈滤波器输入向量 (使用之前的判决)
            Ipp32fc* y_back = ippsMalloc_32fc(L2);
            for (int j = 0; j < L2; j++) {
                int idx = num - 1 - j;
                if (idx >= 0 && idx < NumTotalBit / Q) {
                    y_back[j] = SignalAftW[idx];
                }
                else {
                    y_back[j].re = 0.0f;
                    y_back[j].im = 0.0f;
                }
            }

            // 计算反馈滤波器输出 qn
            Ipp32fc qn = { 0, 0 };
            ippsDotProd_32fc(w2, y_back, L2, &qn);

            // 合并输入向量为u = [y; y_back]
            Ipp32fc* u = ippsMalloc_32fc(L1 + L2);
            ippsCopy_32fc(y, u, L1);
            ippsCopy_32fc(y_back, u + L1, L2);

            // 计算均衡器输出
            daiding[num].re = pn.re + qn.re;
            daiding[num].im = pn.im + qn.im;
            temp[num] = daiding[num];

            // 硬判决(找到最近的星座点)
            Ipp64f* Distance = ippsMalloc_64f(TableSize);
            for (int t = 0; t < TableSize; t++) {
                Ipp32fc diff;
                ippsSub_32fc(&temp[num], &Table[t], &diff, 1);
                Ipp64f dist;
                ippsNorm_L2_32fc64f(&diff, 1, &dist);
                Distance[t] = dist;
            }

            // 查找最小距离对应的星座点
            Ipp64f minDist;
            int minIdx;
            ippsMinIndx_64f(Distance, TableSize, &minDist, &minIdx);
            decision[num] = Table[minIdx];

            // 计算误差
            Error[num].re = decision[num].re - temp[num].re;
            Error[num].im = decision[num].im - temp[num].im;

            // 保存决策结果
            SignalAftW[num] = decision[num];

            // 更新权重和相关矩阵 (RLS算法)
            Ipp32fc* aa = ippsMalloc_32fc(L1 + L2);
            ippsZero_32fc(aa, L1 + L2);

            // 计算 aa = p * u
            for (int row = 0; row < L1 + L2; row++) {
                Ipp32fc sum = { 0, 0 };
                for (int col = 0; col < L1 + L2; col++) {
                    Ipp32fc product;
                    ippsMul_32fc(&p[row * (L1 + L2) + col], &u[col], &product, 1);
                    sum.re += product.re;
                    sum.im += product.im;
                }
                aa[row] = sum;
            }

            // 计算 bb = Lambda + u' * aa
            Ipp32fc bb = { Lambda, 0 };
            for (int j = 0; j < L1 + L2; j++) {
                Ipp32fc u_conj = { u[j].re, -u[j].im };
                Ipp32fc product;
                ippsMul_32fc(&u_conj, &aa[j], &product, 1);
                bb.re += product.re;
                bb.im += product.im;
            }

            // 计算 k = aa / bb
            Ipp32fc* k = ippsMalloc_32fc(L1 + L2);
            for (int j = 0; j < L1 + L2; j++) {
                Ipp32fc divisor = {
                    (bb.re * aa[j].re + bb.im * aa[j].im) / (bb.re * bb.re + bb.im * bb.im),
                    (bb.re * aa[j].im - bb.im * aa[j].re) / (bb.re * bb.re + bb.im * bb.im)
                };
                k[j] = divisor;
            }

            // 更新相关矩阵 p = (p - k * u' * p) / Lambda
            Ipp32fc* primer = ippsMalloc_32fc((L1 + L2) * (L1 + L2));
            ippsZero_32fc(primer, (L1 + L2) * (L1 + L2));

            // 计算 primer = k * u' * p
            for (int row = 0; row < L1 + L2; row++) {
                for (int col = 0; col < L1 + L2; col++) {
                    Ipp32fc sum = { 0, 0 };
                    for (int j = 0; j < L1 + L2; j++) {
                        Ipp32fc u_conj = { u[j].re, -u[j].im };
                        Ipp32fc temp1, temp2;
                        ippsMul_32fc(&k[row], &u_conj, &temp1, 1);
                        ippsMul_32fc(&temp1, &p[j * (L1 + L2) + col], &temp2, 1);
                        sum.re += temp2.re;
                        sum.im += temp2.im;
                    }
                    primer[row * (L1 + L2) + col] = sum;
                }
            }

            // 计算 p = (p - primer) / Lambda
            for (int j = 0; j < (L1 + L2) * (L1 + L2); j++) {
                p[j].re = (p[j].re - primer[j].re) / Lambda;
                p[j].im = (p[j].im - primer[j].im) / Lambda;
            }

            // 计算鉴相器输出
            Ipp32fc pn_conj = { pn.re, -pn.im };
            Ipp32fc error_plus_pn = { Error[num].re + pn.re, Error[num].im + pn.im };
            Ipp32fc discr_complex;
            ippsMul_32fc(&pn_conj, &error_plus_pn, &discr_complex, 1);
            Discriminator_Out[num] = discr_complex.im;

            // 更新NCO相位
            if (num >= 2) {
                NCO_Phase[num] = 2 * NCO_Phase[num - 1] - NCO_Phase[num - 2] +
                    PLL1 * Discriminator_Out[num] - PLL2 * Discriminator_Out[num - 1];
            }

            // 更新权重 w = w + k * Error[num]
            for (int j = 0; j < L1 + L2; j++) {
                Ipp32fc product;
                ippsMul_32fc(&k[j], &Error[num], &product, 1);
                w[j].re += product.re;
                w[j].im += product.im;
            }

            // 释放临时内存
            ippsFree(y_back);
            ippsFree(u);
            ippsFree(aa);
            ippsFree(k);
            ippsFree(primer);
            ippsFree(Distance);
        }
        ippsFree(y);
    }

    // 释放内存
    ippsFree(w);
    ippsFree(p);
    ippsFree(Error);
    ippsFree(NCO_Phase);
    ippsFree(Discriminator_Out);
    ippsFree(daiding);
    ippsFree(temp);
    ippsFree(decision);
}

void VI_SBL_channel_estimation(const Ipp32fc* signal_rx, const Ipp32fc* signal_tx, int rx_length, int tx_length, int channel_length, int iter, Ipp32fc* mu, Ipp32f* epsilon_mean)
{
    int L = channel_length;

    // Construct the received signal segment y = signal_rx(L:end)
    int y_length = rx_length - L + 1;
    Ipp32fc* y = ippsMalloc_32fc(y_length);
    ippsCopy_32fc(signal_rx + L - 1, y, y_length);

    // Construct the Toeplitz matrix X
    // X = toeplitz(signal_tx(L:end), signal_tx(L:-1:1))
    int N = y_length; // Number of rows in X
    Ipp32fc* X = ippsMalloc_32fc(N * L);

    // Fill the Toeplitz matrix X
    for (int row = 0; row < N; row++) {
        for (int col = 0; col < L; col++) {
            if (row + col < tx_length) {
                X[row * L + col] = signal_tx[row + L - 1 - col];
            }
            else {
                X[row * L + col].re = 0.0f;
                X[row * L + col].im = 0.0f;
            }
        }
    }

    // Initialize parameters
    // a and b are parameters of gamma prior
    Ipp32f a_initial = 1e-5f;
    Ipp32f b_initial = 1e-5f;
    Ipp32f* a = ippsMalloc_32f(L);
    Ipp32f* b = ippsMalloc_32f(L);
    ippsSet_32f(a_initial, a, L);
    ippsSet_32f(b_initial, b, L);

    // c and d are parameters of epsilon (noise precision) prior
    Ipp32f c = 1e-5f;
    Ipp32f d = 1e-5f;

    // Initialize epsilon_mean
    *epsilon_mean = c / d;

    // Allocate memory for intermediate computations
    Ipp32fc* Sigma = ippsMalloc_32fc(L * L);      // Posterior covariance matrix
    Ipp32fc* X_transpose = ippsMalloc_32fc(L * N); // X^T
    Ipp32fc* X_transpose_X = ippsMalloc_32fc(L * L); // X^T * X
    Ipp32fc* X_transpose_y = ippsMalloc_32fc(L);    // X^T * y
    Ipp32fc* Tao = ippsMalloc_32fc(L * L);         // Diagonal matrix of a/b
    Ipp32fc* Tao_plus_epsilonXTX = ippsMalloc_32fc(L * L); // Tao + epsilon_mean * X^T * X
    Ipp32fc* temp_L = ippsMalloc_32fc(L);         // Temporary vector of length L
    Ipp32fc* X_mu = ippsMalloc_32fc(N);           // X * mu
    Ipp32fc* y_minus_X_mu = ippsMalloc_32fc(N);   // y - X * mu
    Ipp32fc* X_Sigma = ippsMalloc_32fc(N * L);    // X * Sigma
    Ipp32fc* X_Sigma_XT = ippsMalloc_32fc(N * N); // X * Sigma * X^T

    // Memory for matrix inversion using MKL
    int* ipiv = ippsMalloc_32s(L);       // Pivot indices for LU decomposition

    // Compute X^T
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < L; j++) {
            X_transpose[j * N + i].re = X[i * L + j].re;
            X_transpose[j * N + i].im = -X[i * L + j].im; // Conjugate transpose
        }
    }

    // Compute X^T * X
    // Use CBLAS for complex matrix multiplication
    Ipp32fc alpha = { 1.0f, 0.0f };
    Ipp32fc beta = { 0.0f, 0.0f };
    cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
        L, L, N,
        &alpha, X_transpose, N, X, L,
        &beta, X_transpose_X, L);

    // Compute X^T * y
    cblas_cgemv(CblasRowMajor, CblasNoTrans,
        L, N,
        &alpha, X_transpose, N,
        y, 1,
        &beta, X_transpose_y, 1);

    // VI Iteration
    for (int i = 0; i < iter; i++) {
        // Update q(h)
        *epsilon_mean = c / d;

        // Construct diagonal matrix Tao = diag(a./b)
        ippsZero_32fc(Tao, L * L);
        for (int j = 0; j < L; j++) {
            Tao[j * L + j].re = a[j] / b[j];
            Tao[j * L + j].im = 0.0f;
        }

        // Compute Tao_plus_epsilonXTX = Tao + epsilon_mean * X^T * X
        ippsZero_32fc(Tao_plus_epsilonXTX, L * L);
        for (int row = 0; row < L; row++) {
            for (int col = 0; col < L; col++) {
                Tao_plus_epsilonXTX[row * L + col].re = Tao[row * L + col].re +
                    (*epsilon_mean) * X_transpose_X[row * L + col].re;
                Tao_plus_epsilonXTX[row * L + col].im = Tao[row * L + col].im +
                    (*epsilon_mean) * X_transpose_X[row * L + col].im;
            }
        }

        // Compute Sigma = inv(Tao_plus_epsilonXTX)
        // Using LAPACK for matrix inversion via MKL

        // Convert Ipp32fc to MKL_Complex8
        MKL_Complex8* mkl_matrix = (MKL_Complex8*)mkl_malloc(L * L * sizeof(MKL_Complex8), 64);
        for (int k = 0; k < L * L; k++) {
            mkl_matrix[k].real = Tao_plus_epsilonXTX[k].re;
            mkl_matrix[k].imag = Tao_plus_epsilonXTX[k].im;
        }

        // Perform LU factorization
        int info = LAPACKE_cgetrf(LAPACK_ROW_MAJOR, L, L, mkl_matrix, L, ipiv);
        if (info != 0) {
            printf("LU decomposition failed with error code %d\n", info);
            // Handle error
        }

        // Compute the inverse
        info = LAPACKE_cgetri(LAPACK_ROW_MAJOR, L, mkl_matrix, L, ipiv);
        if (info != 0) {
            printf("Matrix inversion failed with error code %d\n", info);
            // Handle error
        }

        // Convert back to Ipp32fc
        for (int k = 0; k < L * L; k++) {
            Sigma[k].re = mkl_matrix[k].real;
            Sigma[k].im = mkl_matrix[k].imag;
        }

        mkl_free(mkl_matrix);

        // Compute mu = epsilon_mean * Sigma * X^T * y
        // First compute temp_L = Sigma * X^T * y
        cblas_cgemv(CblasRowMajor, CblasNoTrans,
            L, L,
            &alpha, Sigma, L,
            X_transpose_y, 1,
            &beta, temp_L, 1);

        // Then scale by epsilon_mean
        Ipp32fc eps_complex = { *epsilon_mean, 0.0f };
        ippsMulC_32fc(temp_L, eps_complex, mu, L);

        // Update q(γ)
        // a = a + 1
        ippsAddC_32f_I(1.0f, a, L);

        // b = b + abs(mu).^2 + diag(Sigma)
        for (int j = 0; j < L; j++) {
            Ipp32f mu_abs_squared = mu[j].re * mu[j].re + mu[j].im * mu[j].im;
            Ipp32f sigma_diag = Sigma[j * L + j].re; // Diagonal of Sigma (real part only for covariance)
            b[j] = b[j] + mu_abs_squared + sigma_diag;
        }

        // Update q(ε)
        // c = N + c
        c = N + c;

        // Compute X * mu
        cblas_cgemv(CblasRowMajor, CblasNoTrans,
            N, L,
            &alpha, X, L,
            mu, 1,
            &beta, X_mu, 1);

        // Compute y - X * mu
        ippsSub_32fc(y, X_mu, y_minus_X_mu, N);

        // Compute norm(y - X * mu, 2)^2
        Ipp64f norm_squared;
        ippsNorm_L2_32fc64f(y_minus_X_mu, N, (Ipp64f*)&norm_squared);
        norm_squared = norm_squared * norm_squared;

        // Compute trace(X * Sigma * X^T)
        // First compute X * Sigma
        cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
            N, L, L,
            &alpha, X, L,
            Sigma, L,
            &beta, X_Sigma, L);

        // Then compute X_Sigma * X^T
        cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasTrans,
            N, N, L,
            &alpha, X_Sigma, L,
            X, L,
            &beta, X_Sigma_XT, N);

        // Compute trace of X_Sigma_XT (sum of diagonal elements)
        Ipp32f trace = 0.0f;
        for (int j = 0; j < N; j++) {
            trace += X_Sigma_XT[j * N + j].re;
        }

        // Update d
        d = d + norm_squared + trace;
    }

    // Free allocated memory
    ippsFree(y);
    ippsFree(X);
    ippsFree(a);
    ippsFree(b);
    ippsFree(Sigma);
    ippsFree(X_transpose);
    ippsFree(X_transpose_X);
    ippsFree(X_transpose_y);
    ippsFree(Tao);
    ippsFree(Tao_plus_epsilonXTX);
    ippsFree(temp_L);
    ippsFree(X_mu);
    ippsFree(y_minus_X_mu);
    ippsFree(X_Sigma);
    ippsFree(X_Sigma_XT);
    ippsFree(ipiv);
}

void MIMO_Syn(Ipp32u MaxCacheFrameCnt, Ipp8u* pSyn_StepCnt, Ipp8u* pSyn_DataCacheCnt, Ipp32fc* Syn_DataCache, Ipp32fc* Syn_DataCachePrmy, Ipp32fc* Sig_blk, Ipp32f* Syn_SigIn, Ipp32s Syn_SigLen, Ipp32fc* Syn_FIRCoe, Ipp32s Syn_FIRLen, Ipp32fc* Syn_RefCopySam, Ipp32fc* Syn_RefCopyAll, Ipp8u* Syn_Flag, Ipp32f* Syn_SigRec, Ipp32f g_Syn_Threshold)
{
    Ipp16u MaxNum = 0;
    MaxNum = MaxCacheFrameCnt;

    Ipp32fc* BaseBandSig = ippsMalloc_32fc(g_Syn_BufCnt);
    ippsZero_32fc(BaseBandSig, g_Syn_BufCnt);
    if (*pSyn_StepCnt == 0) //粗同步阶段
    {
        //初始化
        Ipp32s Syn_PosFirst = -1;
        Ipp8u Syn_FlagFirst = 0;
        //Step1 对实时接收到的6144点信号做降采样和滤波,输出基带的6144点信号

        //DownConversion(Syn_SigIn, Syn_SigLen, Syn_FIRCoe, Syn_FIRLen, BaseBandSig);
        Rev2Cpl_SC(Syn_SigIn, Syn_SigLen, BaseBandSig);
        //Step2 对基带的6144点信号做一次粗同步,输出同步结果和2048点的检测向量Sig_blk
        SynStep1_SC_Edited(Syn_SigIn, BaseBandSig, g_Syn_BufCnt, Syn_RefCopySam,
            Sig_blk, Syn_DataCache, Syn_DataCachePrmy, &Syn_PosFirst,
            &Syn_FlagFirst, Syn_Threshold, g_Syn_NFFT_RAW, g_Syn_BufSamCnt, g_Syn_BufCnt, g_SamStep);

        if (Syn_FlagFirst == 1)
        {
            *pSyn_StepCnt = 1;
        }
    }
    else if (*pSyn_StepCnt == 1)//缓存阶段
    {
        if (*pSyn_DataCacheCnt == MaxCacheFrameCnt)
        {
            *pSyn_StepCnt = 2;//进入细同步的标志位置位
        }
        else
        {
            Ipp32fc* Syn_SigInCplx = ippsMalloc_32fc(g_Syn_BufCnt);
            Rev2Cpl_SC(Syn_SigIn, g_Syn_BufCnt, Syn_SigInCplx);
            ippsCopy_32fc(Syn_SigInCplx, Syn_DataCache + g_Syn_BufCnt * 2 + (*pSyn_DataCacheCnt) * g_Syn_BufCnt, g_Syn_BufCnt);
            ippsCopy_32fc(Syn_SigInCplx, Syn_DataCachePrmy + g_Syn_BufCnt * 2 + (*pSyn_DataCacheCnt) * g_Syn_BufCnt, g_Syn_BufCnt);
            (*pSyn_DataCacheCnt)++;
            ippsFree(Syn_SigInCplx);

        }
    }
    else if (*pSyn_StepCnt == 2)//细同步阶段
    {

        Ipp32s Syn_PosSecond = -1;
        //SynStep2_SC(Syn_DataCache, Syn_DataCachePrmy, Syn_RefCopyAll, &Syn_PosSecond, Syn_SigRec);


        Ipp32f* Syn_DataCachePrmy_Real = ippsMalloc_32f(Signal_After_BP_lenth + g_LFM2Data_lenth * 2);
        Ipp32f* Syn_RefCopyAll_Real = ippsMalloc_32f(g_LFM2Data_lenth);
        //Ipp32f* Syn_SigRec_Real = ippsMalloc_32f(g_InfoSamPointTotalSyn);


        Cpl2Rev_SC(Syn_DataCachePrmy, Signal_After_BP_lenth + g_LFM2Data_lenth * 2, Syn_DataCachePrmy_Real);
        Cpl2Rev_SC(Syn_RefCopyAll, g_LFM2Data_lenth, Syn_RefCopyAll_Real);

        Sync_SC(Syn_DataCachePrmy_Real, Syn_RefCopyAll_Real,
            &Syn_PosSecond, Syn_SigRec);


        *Syn_Flag = 1;//同步成功标志位置位
    }
    else
    {
        printf("同步错误，请检查参数 *pSyn_StepCnt");
    }

    ippsFree(BaseBandSig);
}

void MIMO_Syn_Edited(Ipp32u MaxCacheFrameCnt, Ipp8u* pSyn_StepCnt, Ipp8u* pSyn_DataCacheCnt, Ipp32fc* Syn_DataCache, Ipp32fc* Syn_DataCachePrmy, 
    Ipp32fc* Sig_blk, Ipp32f* Syn_SigIn, Ipp32s Syn_SigLen,Ipp32fc* Syn_RefCopySam, Ipp32fc* Syn_RefCopyAll, Ipp8u* Syn_Flag, 
    Ipp32f* Syn_SigRec, Ipp32f g_Syn_Threshold, Ipp32s va_g_Syn_BufCnt, Ipp32s va_g_Syn_NFFT_RAW, Ipp32s va_g_Syn_BufSamCnt, 
    Ipp32s va_g_SamStep, Ipp32s va_Signal_After_BP_lenth, Ipp32s va_g_LFM2Data_lenth, Ipp32s va_g_InfoSamPointTotalSyn, Ipp32s va_g_fs, 
    Ipp32s va_DelayLen, Ipp32f va_Syn_Threshold, Ipp32fc* Syn_DataCachePrmy_COPY)
{
    Ipp16u MaxNum = 0;
    MaxNum = MaxCacheFrameCnt;

    Ipp32fc* BaseBandSig = ippsMalloc_32fc(va_g_Syn_BufCnt);
    ippsZero_32fc(BaseBandSig, va_g_Syn_BufCnt);
    if (*pSyn_StepCnt == 0) //粗同步阶段
    {
        //初始化 
        Ipp32s Syn_PosFirst = -1;
        Ipp8u Syn_FlagFirst = 0;
        //Step1 对实时接收到的6144点信号做降采样和滤波,输出基带的6144点信号

        //DownConversion(Syn_SigIn, Syn_SigLen, Syn_FIRCoe, Syn_FIRLen, BaseBandSig);
        Rev2Cpl_SC(Syn_SigIn, Syn_SigLen, BaseBandSig);
        //Step2 对基带的6144点信号做一次粗同步,输出同步结果和2048点的检测向量Sig_blk
        SynStep1_SC_Edited(Syn_SigIn, BaseBandSig, va_g_Syn_BufCnt, Syn_RefCopySam,
            Sig_blk, Syn_DataCache, Syn_DataCachePrmy, &Syn_PosFirst,
            &Syn_FlagFirst, va_Syn_Threshold, va_g_Syn_NFFT_RAW, va_g_Syn_BufSamCnt, va_g_Syn_BufCnt, va_g_SamStep);

        if (Syn_FlagFirst == 1)
        {
            *pSyn_StepCnt = 1;
        }
    }
    else if (*pSyn_StepCnt == 1)//缓存阶段
    {
        if (*pSyn_DataCacheCnt == MaxCacheFrameCnt)
        {
            *pSyn_StepCnt = 2;//进入细同步的标志位置位
        }
        else
        {
            Ipp32fc* Syn_SigInCplx = ippsMalloc_32fc(va_g_Syn_BufCnt);
            Rev2Cpl_SC(Syn_SigIn, va_g_Syn_BufCnt, Syn_SigInCplx);
            ippsCopy_32fc(Syn_SigInCplx, Syn_DataCache + va_g_Syn_BufCnt * 2 + (*pSyn_DataCacheCnt) * va_g_Syn_BufCnt, va_g_Syn_BufCnt);
            ippsCopy_32fc(Syn_SigInCplx, Syn_DataCachePrmy + va_g_Syn_BufCnt * 2 + (*pSyn_DataCacheCnt) * va_g_Syn_BufCnt, va_g_Syn_BufCnt);
            (*pSyn_DataCacheCnt)++;
            ippsFree(Syn_SigInCplx);

        }
    }
    else if (*pSyn_StepCnt == 2)//细同步阶段
    {

        Ipp32s Syn_PosSecond = -1;
        //SynStep2_SC(Syn_DataCache, Syn_DataCachePrmy, Syn_RefCopyAll, &Syn_PosSecond, Syn_SigRec);


        Ipp32f* Syn_DataCachePrmy_Real = ippsMalloc_32f(va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2);
        Ipp32f* Syn_RefCopyAll_Real = ippsMalloc_32f(va_g_LFM2Data_lenth);
        //Ipp32f* Syn_SigRec_Real = ippsMalloc_32f(g_InfoSamPointTotalSyn);


        Cpl2Rev_SC(Syn_DataCachePrmy, va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2, Syn_DataCachePrmy_Real);
        Cpl2Rev_SC(Syn_RefCopyAll, va_g_LFM2Data_lenth, Syn_RefCopyAll_Real);
        //Save32fData("TEST_523.txt", Syn_DataCachePrmy_Real, 20*8192);
        ippsCopy_32fc(Syn_DataCachePrmy, Syn_DataCachePrmy_COPY, va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2);


        
        Sync_SC_Edited(Syn_DataCachePrmy_Real, Syn_RefCopyAll_Real,
            &Syn_PosSecond, Syn_SigRec, va_Signal_After_BP_lenth,
            va_g_LFM2Data_lenth, va_g_InfoSamPointTotalSyn, va_g_fs, va_DelayLen);
        *Syn_Flag = 1;//同步成功标志位置位
    }
    else
    {
        printf("同步错误，请检查参数 *pSyn_StepCnt");
    }

    ippsFree(BaseBandSig);
}

void MASS_Syn_Edited(Ipp32u MaxCacheFrameCnt, Ipp8u* pSyn_StepCnt, Ipp8u* pSyn_DataCacheCnt, Ipp32fc* Syn_DataCache, Ipp32fc* Syn_DataCachePrmy, Ipp32fc* Sig_blk, Ipp32f* Syn_SigIn, Ipp32s Syn_SigLen, Ipp32fc* Syn_RefCopySam, Ipp32fc* Syn_RefCopyAll, Ipp8u* Syn_Flag, Ipp32f* Syn_SigRec, Ipp32f g_Syn_Threshold, Ipp32s va_g_Syn_BufCnt, Ipp32s va_g_Syn_NFFT_RAW, Ipp32s va_g_Syn_BufSamCnt, Ipp32s va_g_SamStep, Ipp32s va_Signal_After_BP_lenth, Ipp32s va_g_LFM2Data_lenth, Ipp32s va_g_InfoSamPointTotalSyn, Ipp32s va_g_fs, Ipp32s va_DelayLen, Ipp32f va_Syn_Threshold, Ipp32f* Channel_Length, Ipp32f* Syn2_CorrCur_Padded_Copy)
{
    Ipp16u MaxNum = 0;
    MaxNum = MaxCacheFrameCnt;

    Ipp32fc* BaseBandSig = ippsMalloc_32fc(va_g_Syn_BufCnt);
    ippsZero_32fc(BaseBandSig, va_g_Syn_BufCnt);
    if (*pSyn_StepCnt == 0) //粗同步阶段
    {
        //初始化 
        Ipp32s Syn_PosFirst = -1;
        Ipp8u Syn_FlagFirst = 0;
        //Step1 对实时接收到的6144点信号做降采样和滤波,输出基带的6144点信号

        //DownConversion(Syn_SigIn, Syn_SigLen, Syn_FIRCoe, Syn_FIRLen, BaseBandSig);
        Rev2Cpl_SC(Syn_SigIn, Syn_SigLen, BaseBandSig);
        //Step2 对基带的6144点信号做一次粗同步,输出同步结果和2048点的检测向量Sig_blk
        SynStep1_SC_Edited(Syn_SigIn, BaseBandSig, va_g_Syn_BufCnt, Syn_RefCopySam,
            Sig_blk, Syn_DataCache, Syn_DataCachePrmy, &Syn_PosFirst,
            &Syn_FlagFirst, va_Syn_Threshold, va_g_Syn_NFFT_RAW, va_g_Syn_BufSamCnt, va_g_Syn_BufCnt, va_g_SamStep);

        if (Syn_FlagFirst == 1)
        {
            *pSyn_StepCnt = 1;
            int a = 1;
        }
    }
    else if (*pSyn_StepCnt == 1)//缓存阶段
    {
        if (*pSyn_DataCacheCnt == MaxCacheFrameCnt)
        {
            *pSyn_StepCnt = 2;//进入细同步的标志位置位
        }
        else
        {
            Ipp32fc* Syn_SigInCplx = ippsMalloc_32fc(va_g_Syn_BufCnt);
            Rev2Cpl_SC(Syn_SigIn, va_g_Syn_BufCnt, Syn_SigInCplx);
            ippsCopy_32fc(Syn_SigInCplx, Syn_DataCache + va_g_Syn_BufCnt * 2 + (*pSyn_DataCacheCnt) * va_g_Syn_BufCnt, va_g_Syn_BufCnt);
            ippsCopy_32fc(Syn_SigInCplx, Syn_DataCachePrmy + va_g_Syn_BufCnt * 2 + (*pSyn_DataCacheCnt) * va_g_Syn_BufCnt, va_g_Syn_BufCnt);
            (*pSyn_DataCacheCnt)++;
            ippsFree(Syn_SigInCplx);

        }
    }
    else if (*pSyn_StepCnt == 2)//细同步阶段
    {

        Ipp32s Syn_PosSecond = -1;
        //SynStep2_SC(Syn_DataCache, Syn_DataCachePrmy, Syn_RefCopyAll, &Syn_PosSecond, Syn_SigRec);


        Ipp32f* Syn_DataCachePrmy_Real = ippsMalloc_32f(va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2);
        Ipp32f* Syn_RefCopyAll_Real = ippsMalloc_32f(va_g_LFM2Data_lenth);
        //Ipp32f* Syn_SigRec_Real = ippsMalloc_32f(g_InfoSamPointTotalSyn);


        Cpl2Rev_SC(Syn_DataCachePrmy, va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2, Syn_DataCachePrmy_Real);
        Cpl2Rev_SC(Syn_RefCopyAll, va_g_LFM2Data_lenth, Syn_RefCopyAll_Real);
        //Save32fData("TEST_523.txt", Syn_DataCachePrmy_Real, 20*8192);
        MASS_Sync_SC_Edited(Syn_DataCachePrmy_Real, Syn_RefCopyAll_Real,
            &Syn_PosSecond, Syn_SigRec, va_Signal_After_BP_lenth,
            va_g_LFM2Data_lenth, va_g_InfoSamPointTotalSyn, va_g_fs, va_DelayLen,Channel_Length,Syn2_CorrCur_Padded_Copy);

        *Syn_Flag = 1;//同步成功标志位置位
    }
    else
    {
        printf("同步错误，请检查参数 *pSyn_StepCnt");
    }

    ippsFree(BaseBandSig);
}

void SynStep1_SC(Ipp32f* Syn_SigIn, Ipp32fc* BaseBandSig, Ipp32s Syn_SigLen, Ipp32fc* Syn_RefCopySam, Ipp32fc* Sig_blk, Ipp32fc* Syn_DataCache, Ipp32fc* Syn_DataCachePrmy, Ipp32s* Syn_PosFirst, Ipp8u* Syn_FlagFirst, Ipp32f g_Syn_Threshold)
{
    //同步标志位和同步坐标初始化
    Ipp32u Step = g_Syn_NFFT_RAW / 2;
    ///Section1 对得到的基带信号抽样
    Ipp32fc* BaseBandSigSam = ippsMalloc_32fc(g_Syn_BufSamCnt);
    Ipp32u SamCnt = 0;
    for (SamCnt = 0; SamCnt < g_Syn_BufSamCnt; SamCnt++)
    {
        *(BaseBandSigSam + SamCnt) = *(BaseBandSig + SamCnt * g_SamStep);
    }
    ///Section2 频域实现拷贝相关器
    Ipp32fc* Syn_SigInfc = ippsMalloc_32fc(g_Syn_BufCnt);
    //把Syn_DataCachePrmy第二个6144点信号移到前半部分，刚得到的6144点同步信号放入后半部分
    ippsMove_32fc(Syn_DataCachePrmy + g_Syn_BufCnt, Syn_DataCachePrmy, g_Syn_BufCnt);

    Rev2Cpl_SC(Syn_SigIn, g_Syn_BufCnt, Syn_SigInfc);
    ippsMove_32fc(Syn_SigInfc, Syn_DataCachePrmy + g_Syn_BufCnt, g_Syn_BufCnt);
    //把Syn_DataCache第二个6144点信号移到前半部分，刚得到的6144点同步信号放入后半部分
    ippsMove_32fc(Syn_DataCache + g_Syn_BufCnt, Syn_DataCache, g_Syn_BufCnt);
    ippsMove_32fc(BaseBandSig, Syn_DataCache + g_Syn_BufCnt, g_Syn_BufCnt);
    //把Sig_blk后半部分信号移到前半部分，刚抽样得到的1024点同步信号放入后半部分
    ippsMove_32fc(Sig_blk + Step, Sig_blk, Step);
    ippsMove_32fc(BaseBandSigSam, Sig_blk + Step, Step);
    //求向量总能量,归一化
    Ipp64fc  Norm = { 0,0 };
    Ipp32fc  Norm32 = { 0,0 };
    Ipp32fc* SigDownblk = ippsMalloc_32fc(g_Syn_NFFT_RAW);
    Ipp32fc* SigDownblk_FD = ippsMalloc_32fc(g_Syn_NFFT_RAW);
    Ipp32fc* Syn_DotMul_FD = ippsMalloc_32fc(g_Syn_NFFT_RAW);
    Ipp32fc* CorrCur = ippsMalloc_32fc(g_Syn_NFFT_RAW);
    Ipp32f* CorrCurAbs = ippsMalloc_32f(g_Syn_NFFT_RAW);
    ippsNorm_L2_32fc64f(Sig_blk, g_Syn_NFFT_RAW, &(Norm.re));
    Norm32.re = (Ipp32f)Norm.re;
    ippsDivC_32fc(Sig_blk, Norm32, SigDownblk, g_Syn_NFFT_RAW);
    //FFT,点乘，IFFT
    Ipps_FFT_32fc_SC(SigDownblk, SigDownblk_FD, g_Syn_NFFT_RAW);
    ippsMul_32fc(SigDownblk_FD, Syn_RefCopySam, Syn_DotMul_FD, g_Syn_NFFT_RAW);
    Ipps_IFFT_32fc_SC(Syn_DotMul_FD, CorrCur, g_Syn_NFFT_RAW);
    //对相关结果取模
    ippsMagnitude_32fc(CorrCur, CorrCurAbs, g_Syn_NFFT_RAW);
    ///判断相关峰是否大于阈值
    Ipp32f MaxAbsCur = 0;
    Ipp32s MaxIndx = 0;
    ippsMaxAbsIndx_32f(CorrCurAbs + Step - 1, Step + 1, &MaxAbsCur, &MaxIndx);
    if (MaxAbsCur > g_Syn_Threshold)
    {
        *Syn_FlagFirst = 1;
        *Syn_PosFirst = MaxIndx * g_SamStep + g_Syn_BufCnt;
    }
    else
    {
        *Syn_FlagFirst = 0;
        *Syn_PosFirst = -1;
    }
    //释放内存
    ippsFree(BaseBandSigSam);
    ippsFree(SigDownblk);
    ippsFree(SigDownblk_FD);
    ippsFree(Syn_DotMul_FD);
    ippsFree(CorrCur);
    ippsFree(CorrCurAbs);
    ippsFree(Syn_SigInfc);
}

void MIMO_syn_dopl_baseband_Process_Edited(Ipp32f* Syn_SigRec_1, Ipp32f* Syn_SigRec_2, Ipp32f* Syn_SigRec_3, Ipp32f* Syn_SigRec_4, int N_block, Ipp32fc* UWParts, Ipp32fc* DataParts, Ipp32s va_N_g, Ipp32s va_g_Syn_NFFT, Ipp32s va_g_InfoSamPointTotalSyn, Ipp32s va_N_upsample, Ipp32s va_g_f0, Ipp32s va_g_fs, Ipp32s va_Syn_FIRLen)
{
    //信道1
    Ipp32fc* UWParts_temp_1 = ippsMalloc_32fc(N_block * va_N_g);
    Ipp32fc* DataParts_temp_1 = ippsMalloc_32fc(N_block * va_g_Syn_NFFT);
    //IQ解调 + 根升余弦滤波器 + 降采样 + 去掉 UW 前缀
    Ipp32fc* DownSampledSig_1 = ippsMalloc_32fc(((va_g_InfoSamPointTotalSyn - (va_Syn_FIRLen - 1) / 2) / va_N_upsample) - va_N_g);
    DownConversion_SC(Syn_SigRec_1, va_g_InfoSamPointTotalSyn, Syn_FIRCoe_SC, Syn_FIRLen,
        DownSampledSig_1, va_g_f0, va_g_fs, va_N_upsample, va_N_g);
    //分块，分为FFT块还有数据块
    SplitBlocksAndSeparate(DownSampledSig_1, ((va_g_InfoSamPointTotalSyn - (va_Syn_FIRLen - 1) / 2) / va_N_upsample) - va_N_g, N_block, UWParts_temp_1, DataParts_temp_1, va_N_g);
    ippsCopy_32fc(UWParts_temp_1, UWParts + 0 * N_block * va_N_g, N_block * va_N_g);
    ippsCopy_32fc(DataParts_temp_1, DataParts + 0 * N_block * va_g_Syn_NFFT, N_block * va_g_Syn_NFFT);
    ippsFree(UWParts_temp_1);
    ippsFree(DataParts_temp_1);
    ippsFree(DownSampledSig_1);

    //信道2
    Ipp32fc* UWParts_temp_2 = ippsMalloc_32fc(N_block * va_N_g);
    Ipp32fc* DataParts_temp_2 = ippsMalloc_32fc(N_block * va_g_Syn_NFFT);
    //IQ解调 + 根升余弦滤波器 + 降采样 + 去掉 UW 前缀
    Ipp32fc* DownSampledSig_2 = ippsMalloc_32fc(((va_g_InfoSamPointTotalSyn - (va_Syn_FIRLen - 1) / 2) / va_N_upsample) - va_N_g);
    DownConversion_SC(Syn_SigRec_2, va_g_InfoSamPointTotalSyn, Syn_FIRCoe_SC, Syn_FIRLen,
        DownSampledSig_2, va_g_f0, va_g_fs, va_N_upsample, va_N_g);
    //分块，分为FFT块还有数据块
    SplitBlocksAndSeparate(DownSampledSig_2, ((va_g_InfoSamPointTotalSyn - (va_Syn_FIRLen - 1) / 2) / va_N_upsample) - va_N_g, N_block, UWParts_temp_2, DataParts_temp_2, va_N_g);
    ippsCopy_32fc(UWParts_temp_2, UWParts + 1 * N_block * va_N_g, N_block * va_N_g);
    ippsCopy_32fc(DataParts_temp_2, DataParts + 1 * N_block * va_g_Syn_NFFT, N_block * va_g_Syn_NFFT);
    ippsFree(UWParts_temp_2);
    ippsFree(DataParts_temp_2);
    ippsFree(DownSampledSig_2);

    //信道3
    Ipp32fc* UWParts_temp_3 = ippsMalloc_32fc(N_block * va_N_g);
    Ipp32fc* DataParts_temp_3 = ippsMalloc_32fc(N_block * va_g_Syn_NFFT);
    //IQ解调 + 根升余弦滤波器 + 降采样 + 去掉 UW 前缀
    Ipp32fc* DownSampledSig_3 = ippsMalloc_32fc(((va_g_InfoSamPointTotalSyn - (va_Syn_FIRLen - 1) / 2) / va_N_upsample) - va_N_g);
    DownConversion_SC(Syn_SigRec_3, va_g_InfoSamPointTotalSyn, Syn_FIRCoe_SC, Syn_FIRLen,
        DownSampledSig_3, va_g_f0, va_g_fs, va_N_upsample, va_N_g);
    //分块，分为FFT块还有数据块
    SplitBlocksAndSeparate(DownSampledSig_3, ((va_g_InfoSamPointTotalSyn - (va_Syn_FIRLen - 1) / 2) / va_N_upsample) - va_N_g, N_block, UWParts_temp_3, DataParts_temp_3, va_N_g);
    ippsCopy_32fc(UWParts_temp_3, UWParts + 2 * N_block * va_N_g, N_block * va_N_g);
    ippsCopy_32fc(DataParts_temp_3, DataParts + 2 * N_block * va_g_Syn_NFFT, N_block * va_g_Syn_NFFT);
    ippsFree(UWParts_temp_3);
    ippsFree(DataParts_temp_3);
    ippsFree(DownSampledSig_3);

    //信道4
    Ipp32fc* UWParts_temp_4 = ippsMalloc_32fc(N_block * va_N_g);
    Ipp32fc* DataParts_temp_4 = ippsMalloc_32fc(N_block * va_g_Syn_NFFT);
    //IQ解调 + 根升余弦滤波器 + 降采样 + 去掉 UW 前缀
    Ipp32fc* DownSampledSig_4 = ippsMalloc_32fc(((va_g_InfoSamPointTotalSyn - (va_Syn_FIRLen - 1) / 2) / va_N_upsample) - va_N_g);
    DownConversion_SC(Syn_SigRec_4, va_g_InfoSamPointTotalSyn, Syn_FIRCoe_SC, Syn_FIRLen,
        DownSampledSig_4, va_g_f0, va_g_fs, va_N_upsample, va_N_g);
    //分块，分为FFT块还有数据块
    SplitBlocksAndSeparate(DownSampledSig_4, ((va_g_InfoSamPointTotalSyn - (va_Syn_FIRLen - 1) / 2) / va_N_upsample) - va_N_g, N_block, UWParts_temp_4, DataParts_temp_4, va_N_g);
    ippsCopy_32fc(UWParts_temp_4, UWParts + 3 * N_block * va_N_g, N_block * va_N_g);
    ippsCopy_32fc(DataParts_temp_4, DataParts + 3 * N_block * va_g_Syn_NFFT, N_block * va_g_Syn_NFFT);
    ippsFree(UWParts_temp_4);
    ippsFree(DataParts_temp_4);
    ippsFree(DownSampledSig_4);
}

void CalcGainVector(Ipp32fc* P, Ipp32fc* u, float Lambda, int n, Ipp32fc* K)
{
    // 计算 P*u
    Ipp32fc* P_u = ippsMalloc_32fc(n);
    ippsZero_32fc(P_u, n);

    for (int row = 0; row < n; row++) {
        Ipp32fc sum = { 0, 0 };
        for (int col = 0; col < n; col++) {
            Ipp32fc product;
            ippsMul_32fc(&P[row * n + col], &u[col], &product, 1);
            sum.re += product.re;
            sum.im += product.im;
        }
        P_u[row] = sum;
    }

    // 计算 u'*P*u
    Ipp32fc u_P_u = { Lambda, 0 }; // 初始值为Lambda
    for (int j = 0; j < n; j++) {
        Ipp32fc u_conj = { u[j].re, -u[j].im };
        Ipp32fc product;
        ippsMul_32fc(&u_conj, &P_u[j], &product, 1);
        u_P_u.re += product.re;
        u_P_u.im += product.im;
    }

    // 计算 K = P_u / u_P_u
    for (int j = 0; j < n; j++) {
        // 复数除法
        float denominator = u_P_u.re * u_P_u.re + u_P_u.im * u_P_u.im;
        K[j].re = (P_u[j].re * u_P_u.re + P_u[j].im * u_P_u.im) / denominator;
        K[j].im = (P_u[j].im * u_P_u.re - P_u[j].re * u_P_u.im) / denominator;
    }

    ippsFree(P_u);
}

void CalcGainVector_64f(Ipp64fc* P, Ipp64fc* u, double Lambda, int n, Ipp64fc* K)
{
    // 计算 P*u
    Ipp64fc* P_u = ippsMalloc_64fc(n);
    ippsZero_64fc(P_u, n);
    for (int row = 0; row < n; row++) {
        Ipp64fc sum = { 0.0, 0.0 };
        for (int col = 0; col < n; col++) {
            Ipp64fc product;
            ippsMul_64fc(&P[row * n + col], &u[col], &product, 1);
            sum.re += product.re;
            sum.im += product.im;
        }
        P_u[row] = sum;
    }

    // 计算 u'*P*u
    Ipp64fc u_P_u = { Lambda, 0.0 }; // 初始值为Lambda
    for (int j = 0; j < n; j++) {
        Ipp64fc u_conj = { u[j].re, -u[j].im };
        Ipp64fc product;
        ippsMul_64fc(&u_conj, &P_u[j], &product, 1);
        u_P_u.re += product.re;
        u_P_u.im += product.im;
    }

    // 计算 K = P_u / u_P_u
    for (int j = 0; j < n; j++) {
        // 复数除法
        double denominator = u_P_u.re * u_P_u.re + u_P_u.im * u_P_u.im;
        K[j].re = (P_u[j].re * u_P_u.re + P_u[j].im * u_P_u.im) / denominator;
        K[j].im = (P_u[j].im * u_P_u.re - P_u[j].re * u_P_u.im) / denominator;
    }

    ippsFree(P_u);
}



void UpdateCorrelationMatrix(Ipp32fc* P, Ipp32fc* K, Ipp32fc* u, float Lambda, int n)
{
    Ipp32fc* K_u_P = ippsMalloc_32fc(n * n);
    ippsZero_32fc(K_u_P, n * n);

    // 计算 K * u' * P
    for (int row = 0; row < n; row++) {
        for (int col = 0; col < n; col++) {
            Ipp32fc sum = { 0, 0 };
            for (int j = 0; j < n; j++) {
                Ipp32fc u_conj = { u[j].re, -u[j].im };
                Ipp32fc temp1, temp2;
                ippsMul_32fc(&K[row], &u_conj, &temp1, 1);
                ippsMul_32fc(&temp1, &P[j * n + col], &temp2, 1);
                sum.re += temp2.re;
                sum.im += temp2.im;
            }
            K_u_P[row * n + col] = sum;
        }
    }

    // 计算 P = (P - K_u_P) / Lambda
    for (int j = 0; j < n * n; j++) {
        P[j].re = (P[j].re - K_u_P[j].re) / Lambda;
        P[j].im = (P[j].im - K_u_P[j].im) / Lambda;
    }

    ippsFree(K_u_P);
}

void UpdateCorrelationMatrix_MKL(Ipp32fc* P, Ipp32fc* K, Ipp32fc* u, float Lambda, int n)
{
    // 分配 MKL 内存
    MKL_Complex8* K_MKL = (MKL_Complex8*)mkl_malloc(n * sizeof(MKL_Complex8), 64);
    MKL_Complex8* u_MKL = (MKL_Complex8*)mkl_malloc(n * sizeof(MKL_Complex8), 64);
    MKL_Complex8* P_MKL = (MKL_Complex8*)mkl_malloc(n * n * sizeof(MKL_Complex8), 64);
    MKL_Complex8* K_u_MKL = (MKL_Complex8*)mkl_malloc(n * n * sizeof(MKL_Complex8), 64);
    MKL_Complex8* K_u_P_MKL = (MKL_Complex8*)mkl_malloc(n * n * sizeof(MKL_Complex8), 64);

    // 将 IPP 数据复制到 MKL 格式
    for (int i = 0; i < n; ++i) {
        K_MKL[i].real = K[i].re;
        K_MKL[i].imag = K[i].im;
        u_MKL[i].real = u[i].re;
        u_MKL[i].imag = u[i].im;
    }

    for (int i = 0; i < n * n; ++i) {
        P_MKL[i].real = P[i].re;
        P_MKL[i].imag = P[i].im;
    }

    // 计算外积 K * u' (n×1 乘以 1×n 得到 n×n)
    // 使用 cblas_cgeru: A = alpha * x * y' + A
    MKL_Complex8 alpha = { 1.0f, 0.0f };
    // 先将 K_u_MKL 置零
    for (int i = 0; i < n * n; ++i) {
        K_u_MKL[i].real = 0.0f;
        K_u_MKL[i].imag = 0.0f;
    }

    // K_u = K * u' (外积)
    cblas_cgerc(CblasRowMajor, n, n, &alpha,
        K_MKL, 1,        // x (n×1)
        u_MKL, 1,        // y (n×1), cgeru 会自动取共轭
        K_u_MKL, n);     // A (n×n)

    // 矩阵乘法: K_u_P = K_u * P
    MKL_Complex8 beta = { 0.0f, 0.0f };
    cblas_cgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
        n, n, n,         // m, n, k
        &alpha,          // alpha
        K_u_MKL, n,      // A (n×n)
        P_MKL, n,        // B (n×n)
        &beta,           // beta
        K_u_P_MKL, n);   // C (n×n)

    // 更新 P = (P - K_u_P) / Lambda
    // 先计算 P = P - K_u_P
    MKL_Complex8 minus_one = { -1.0f, -0.0f };
    cblas_caxpy(n * n, &minus_one, K_u_P_MKL, 1, P_MKL, 1);

    // 再除以 Lambda: P = P / Lambdas
    MKL_Complex8 lambda_inv = { 1.0f / Lambda, 0.0f };
    cblas_cscal(n * n, &lambda_inv, P_MKL, 1);

    // 将结果复制回 IPP 格式
    for (int i = 0; i < n * n; ++i) {
        P[i].re = P_MKL[i].real;
        P[i].im = P_MKL[i].imag;
    }

    // 释放 MKL 内存
    mkl_free(K_MKL);
    mkl_free(u_MKL);
    mkl_free(P_MKL);
    mkl_free(K_u_MKL);
    mkl_free(K_u_P_MKL);
}
void UpdateCorrelationMatrix_MKL_64f(Ipp64fc* P, Ipp64fc* K, Ipp64fc* u, double Lambda, int n)
{
    // 分配 MKL 内存
    MKL_Complex16* K_MKL = (MKL_Complex16*)mkl_malloc(n * sizeof(MKL_Complex16), 64);
    MKL_Complex16* u_MKL = (MKL_Complex16*)mkl_malloc(n * sizeof(MKL_Complex16), 64);
    MKL_Complex16* P_MKL = (MKL_Complex16*)mkl_malloc(n * n * sizeof(MKL_Complex16), 64);
    MKL_Complex16* K_u_MKL = (MKL_Complex16*)mkl_malloc(n * n * sizeof(MKL_Complex16), 64);
    MKL_Complex16* K_u_P_MKL = (MKL_Complex16*)mkl_malloc(n * n * sizeof(MKL_Complex16), 64);

    // 将 IPP 数据复制到 MKL 格式
    for (int i = 0; i < n; ++i) {
        K_MKL[i].real = K[i].re;
        K_MKL[i].imag = K[i].im;
        u_MKL[i].real = u[i].re;
        u_MKL[i].imag = u[i].im;
    }
    for (int i = 0; i < n * n; ++i) {
        P_MKL[i].real = P[i].re;
        P_MKL[i].imag = P[i].im;
    }

    // 计算外积 K * u' (n×1 乘以 1×n 得到 n×n)
    // 使用 cblas_zgeru: A = alpha * x * y' + A
    MKL_Complex16 alpha = { 1.0, 0.0 };

    // 先将 K_u_MKL 置零
    for (int i = 0; i < n * n; ++i) {
        K_u_MKL[i].real = 0.0;
        K_u_MKL[i].imag = 0.0;
    }

    // K_u = K * u' (外积)
    cblas_zgerc(CblasRowMajor, n, n, &alpha,
        K_MKL, 1,        // x (n×1)
        u_MKL, 1,        // y (n×1), zgerc 会自动取共轭
        K_u_MKL, n);     // A (n×n)

    // 矩阵乘法: K_u_P = K_u * P
    MKL_Complex16 beta = { 0.0, 0.0 };
    cblas_zgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
        n, n, n,         // m, n, k
        &alpha,          // alpha
        K_u_MKL, n,      // A (n×n)
        P_MKL, n,        // B (n×n)
        &beta,           // beta
        K_u_P_MKL, n);   // C (n×n)

    // 更新 P = (P - K_u_P) / Lambda
    // 先计算 P = P - K_u_P
    MKL_Complex16 minus_one = { -1.0, 0.0 };
    cblas_zaxpy(n * n, &minus_one, K_u_P_MKL, 1, P_MKL, 1);

    // 再除以 Lambda: P = P / Lambda
    MKL_Complex16 lambda_inv = { 1.0 / Lambda, 0.0 };
    cblas_zscal(n * n, &lambda_inv, P_MKL, 1);

    // 将结果复制回 IPP 格式
    for (int i = 0; i < n * n; ++i) {
        P[i].re = P_MKL[i].real;
        P[i].im = P_MKL[i].imag;
    }

    // 释放 MKL 内存
    mkl_free(K_MKL);
    mkl_free(u_MKL);
    mkl_free(P_MKL);
    mkl_free(K_u_MKL);
    mkl_free(K_u_P_MKL);
}
void UpdateWeights(Ipp32fc* w, Ipp32fc* K, Ipp32fc e_zheng, int n)
{
    for (int j = 0; j < n; j++) {
        Ipp32fc product;
        ippsMul_32fc(&K[j], &e_zheng, &product, 1);
        w[j].re += product.re;
        w[j].im += product.im;
    }
}
void UpdateWeights_64f(Ipp64fc* w, Ipp64fc* K, Ipp64fc e_zheng, int n)
{
    for (int j = 0; j < n; j++) {
        Ipp64fc product;
        ippsMul_64fc(&K[j], &e_zheng, &product, 1);
        w[j].re += product.re;
        w[j].im += product.im;
    }
}





void MDFE_HX(int channel_num, Ipp32fc* sympol, Ipp32fc* reflection, int reflection_size, Ipp32fc* out_frac, int out_frac_length, int n1, int n2, float Delta, float Lambda, float PLL1, float PLL2, int user_num, int bitnum_per, int N_samp, Ipp32fc* x_zheng)
{
    int n = channel_num * n1 + n2;  // 总权重向量长度
    int output_length = user_num / bitnum_per;  // 修改：输出长度为user_num/bitnum_per

    // 分配内存
    Ipp32fc* w_ff = ippsMalloc_32fc(channel_num * n1);
    ippsZero_32fc(w_ff, channel_num * n1);

    Ipp32fc* w_fb = ippsMalloc_32fc(n2);
    ippsZero_32fc(w_fb, n2);

    Ipp32fc* w = ippsMalloc_32fc(n);
    ippsZero_32fc(w, n);

    Ipp32fc* P = ippsMalloc_32fc(n * n);  // 相关矩阵
    ippsZero_32fc(P, n * n);
    // 初始化P为Delta*I
    for (int i = 0; i < n; i++) {
        P[i * n + i].re = Delta;
        P[i * n + i].im = 0.0f;
    }

    Ipp32fc* e_zheng = ippsMalloc_32fc(output_length);
    ippsZero_32fc(e_zheng, output_length);

    Ipp32fc* NCO_Phase = ippsMalloc_32fc(channel_num * (output_length - n1));
    ippsZero_32fc(NCO_Phase, channel_num * (output_length - n1));

    Ipp32f* Discriminator_Out = ippsMalloc_32f(channel_num * (output_length - n1));
    ippsZero_32f(Discriminator_Out, channel_num * (output_length - n1));

    // 新增：决策符号数组
    Ipp32fc* decision_symbol = ippsMalloc_32fc(output_length);
    ippsZero_32fc(decision_symbol, output_length);
    // 初始化前N_samp个决策符号为训练序列
    for (int i = 0; i < N_samp; i++) {
        decision_symbol[i] = sympol[i];
    }

    Ipp32fc* y = ippsMalloc_32fc(channel_num * n1);
    ippsZero_32fc(y, channel_num * n1);

    Ipp32fc* pn = ippsMalloc_32fc(channel_num);
    Ipp32fc* u = ippsMalloc_32fc(n);
    Ipp32fc* y_back = ippsMalloc_32fc(n2);
    Ipp32fc* K = ippsMalloc_32fc(n);

    // 初始化x_zheng
    ippsZero_32fc(x_zheng, output_length);

    // 训练序列部分
    for (int i = 2 * n2 + 1; i < 2 * N_samp + 1; i++) {
        ippsZero_32fc(u, n);
        int num = i / 2;

        for (int count = 0; count < channel_num; count++) {
            // 更新前馈滤波器权重
            ippsCopy_32fc(w + count * n1, w_ff + count * n1, n1);

            // 应用NCO相位校正
            for (int j = 0; j < n1; j++) {
                int idx = i + n1 - 1 - j;
                if (num > 1 && idx < out_frac_length) {  // 修改：防止NCO_Phase越界
                    // 计算NCO相位
                    float phase = fmod(NCO_Phase[count * (output_length - n1) + num - 2].re, 2 * IPP_PI);
                    Ipp32fc phase_rotation = { cos(-phase), sin(-phase) };
                    // 计算一维数组中的索引
                    int linear_idx = idx - 1 + (out_frac_length / channel_num) * count;
                    Ipp32fc temp;
                    ippsMul_32fc(&out_frac[linear_idx], &phase_rotation, &temp, 1);
                    y[count * n1 + j] = temp;
                }
                else {
                    y[count * n1 + j].re = 0.0f;
                    y[count * n1 + j].im = 0.0f;
                }
            }
        }

        ippsCopy_32fc(w + channel_num * n1, w_fb, n2);

        if (i % 2 == 0) {  // 每2个采样点处理一次
            // 准备反馈滤波器输入
            for (int j = 0; j < n2; j++) {
                int idx = num - 1 - j - 1;
                if (idx >= 0 && idx < output_length) {
                    y_back[j] = sympol[idx];
                }
                else {
                    y_back[j].re = 0.0f;
                    y_back[j].im = 0.0f;
                }
            }

            // 计算前馈和反馈输出，组合输入向量
            for (int count = 0; count < channel_num; count++) {
                Ipp32fc dotProduct = { 0, 0 };

                // 创建临时数组来存储w_ff的共轭
                Ipp32fc* w_ff_conj = ippsMalloc_32fc(n1);
                ippsConj_32fc(w_ff + count * n1, w_ff_conj, n1);
                ippsDotProd_32fc(w_ff_conj, y + count * n1, n1, &dotProduct);
                ippsFree(w_ff_conj);

                pn[count] = dotProduct;
                ippsCopy_32fc(y + count * n1, u + count * n1, n1);
            }

            // 设置输入向量u的反馈部分
            ippsCopy_32fc(y_back, u + channel_num * n1, n2);

            // 计算均衡器输出
            Ipp32fc* w_conj = ippsMalloc_32fc(n);
            ippsConj_32fc(w, w_conj, n);
            Ipp32fc dotProduct = { 0, 0 };
            ippsDotProd_32fc(w_conj, u, n, &dotProduct);
            x_zheng[num - 1] = dotProduct;
            ippsFree(w_conj);

            // 计算误差
            e_zheng[num - 1].re = sympol[num - 1].re - x_zheng[num - 1].re;
            e_zheng[num - 1].im = sympol[num - 1].im - x_zheng[num - 1].im;

            // 计算增益向量K
            CalcGainVector(P, u, Lambda, n, K);

            // 更新相关矩阵P
            UpdateCorrelationMatrix_MKL(P, K, u, Lambda, n);

            // 创建 e_zheng[num - 1] 的共轭
            Ipp32fc e_zheng_conj = { e_zheng[num - 1].re, -e_zheng[num - 1].im };

            // 更新权重向量w
            UpdateWeights(w, K, e_zheng_conj, n);

            // 更新锁相环参数
            for (int count = 0; count < channel_num; count++) {
                Ipp32fc error_plus_pn_conj = { e_zheng[num - 1].re + pn[count].re, -e_zheng[num - 1].im - pn[count].im };
                Ipp32fc disc_complex;
                Ipp32fc disc_complex_ln;
                ippsMul_32fc(&pn[count], &error_plus_pn_conj, &disc_complex, 1);
                ippsLn_32fc_A11(&disc_complex, &disc_complex_ln, 1);
                Discriminator_Out[count * (output_length - n1) + num - 1] = disc_complex_ln.im;
                if (num >= 2) {
                    NCO_Phase[count * (output_length - n1) + num - 1].re =
                        2 * NCO_Phase[count * (output_length - n1) + num - 2].re -
                        NCO_Phase[count * (output_length - n1) + num - 3].re +
                        PLL1 * Discriminator_Out[count * (output_length - n1) + num - 1] -
                        PLL2 * Discriminator_Out[count * (output_length - n1) + num - 2];
                    NCO_Phase[count * (output_length - n1) + num - 1].im = 0.0f;
                }
            }
        }
    }

    // 符号均衡部分
    for (int i = 2 * N_samp + 1; i < 2 * (output_length - n1) + 1; i++) {  // 修改：循环边界
        ippsZero_32fc(u, n);
        int num = i / 2;

        for (int count = 0; count < channel_num; count++) {
            // 更新前馈滤波器权重
            ippsCopy_32fc(w + count * n1, w_ff + count * n1, n1);

            // 应用NCO相位校正
            for (int j = 0; j < n1; j++) {
                int idx = i + n1 - 1 - j;
                if (num > 1 && idx < out_frac_length) {
                    // 计算NCO相位
                    float phase = fmod(NCO_Phase[count * (output_length - n1) + num - 2].re, 2 * IPP_PI);
                    Ipp32fc phase_rotation = { cos(-phase), sin(-phase) };
                    // 计算一维数组中的索引
                    int linear_idx = idx - 1 + (out_frac_length / channel_num) * count;
                    Ipp32fc temp;
                    ippsMul_32fc(&out_frac[linear_idx], &phase_rotation, &temp, 1);
                    y[count * n1 + j] = temp;
                }
                else {
                    y[count * n1 + j].re = 0.0f;
                    y[count * n1 + j].im = 0.0f;
                }
            }
        }

        ippsCopy_32fc(w + channel_num * n1, w_fb, n2);

        if (i % 2 == 0) {  // 每2个采样点处理一次
            // 准备反馈滤波器输入 - 修改：使用decision_symbol
            for (int j = 0; j < n2; j++) {
                int idx = num - 1 - j - 1;
                if (idx >= 0 && idx < output_length) {
                    y_back[j] = decision_symbol[idx];
                }
                else {
                    y_back[j].re = 0.0f;
                    y_back[j].im = 0.0f;
                }
            }

            // 计算前馈和反馈输出，组合输入向量
            for (int count = 0; count < channel_num; count++) {
                Ipp32fc dotProduct = { 0, 0 };

                // 创建临时数组来存储w_ff的共轭
                Ipp32fc* w_ff_conj = ippsMalloc_32fc(n1);
                ippsConj_32fc(w_ff + count * n1, w_ff_conj, n1);
                ippsDotProd_32fc(w_ff_conj, y + count * n1, n1, &dotProduct);
                ippsFree(w_ff_conj);

                pn[count] = dotProduct;
                ippsCopy_32fc(y + count * n1, u + count * n1, n1);
            }

            // 设置输入向量u的反馈部分
            ippsCopy_32fc(y_back, u + channel_num * n1, n2);

            // 计算均衡器输出
            Ipp32fc* w_conj = ippsMalloc_32fc(n);
            ippsConj_32fc(w, w_conj, n);
            Ipp32fc dotProduct = { 0, 0 };
            ippsDotProd_32fc(w_conj, u, n, &dotProduct);
            //if (i == 28330)
            //{
            //    int a = 1;
            //}
            x_zheng[num - 1] = dotProduct;
            ippsFree(w_conj);

            // 使用硬判决函数
            Ipp32fc temp_decision;
            HardDecision(1, &x_zheng[num - 1], reflection, reflection_size, &temp_decision);
            decision_symbol[num - 1] = temp_decision;  // 新增：存储决策符号

            // 计算误差
            e_zheng[num - 1].re = temp_decision.re - x_zheng[num - 1].re;
            e_zheng[num - 1].im = temp_decision.im - x_zheng[num - 1].im;

            // 计算增益向量K
            CalcGainVector(P, u, Lambda, n, K);

            // 更新相关矩阵P
            UpdateCorrelationMatrix_MKL(P, K, u, Lambda, n);

            // 创建 e_zheng[num - 1] 的共轭
            Ipp32fc e_zheng_conj = { e_zheng[num - 1].re, -e_zheng[num - 1].im };

            // 更新权重向量w
            UpdateWeights(w, K, e_zheng_conj, n);

            // 更新锁相环参数
            for (int count = 0; count < channel_num; count++) {
                Ipp32fc error_plus_pn_conj = { e_zheng[num - 1].re + pn[count].re, -e_zheng[num - 1].im - pn[count].im };
                Ipp32fc disc_complex;
                Ipp32fc disc_complex_ln;
                ippsMul_32fc(&pn[count], &error_plus_pn_conj, &disc_complex, 1);
                ippsLn_32fc_A11(&disc_complex, &disc_complex_ln, 1);
                Discriminator_Out[count * (output_length - n1) + num - 1] = disc_complex_ln.im;
                if (num >= 2) {
                    NCO_Phase[count * (output_length - n1) + num - 1].re =
                        2 * NCO_Phase[count * (output_length - n1) + num - 2].re -
                        NCO_Phase[count * (output_length - n1) + num - 3].re +
                        PLL1 * Discriminator_Out[count * (output_length - n1) + num - 1] -
                        PLL2 * Discriminator_Out[count * (output_length - n1) + num - 2];
                    NCO_Phase[count * (output_length - n1) + num - 1].im = 0.0f;
                }
            }
        }
    }

    // 释放内存
    ippsFree(w_ff);
    ippsFree(w_fb);
    ippsFree(w);
    ippsFree(P);
    ippsFree(e_zheng);
    ippsFree(NCO_Phase);
    ippsFree(Discriminator_Out);
    ippsFree(decision_symbol);  // 新增：释放决策符号数组
    ippsFree(y);
    ippsFree(pn);
    ippsFree(u);
    ippsFree(y_back);
    ippsFree(K);
}


void MDFE_HX_64f(int channel_num, Ipp32fc* sympol, Ipp32fc* reflection, int reflection_size, Ipp32fc* out_frac, int out_frac_length, int n1, int n2, float Delta, float Lambda, float PLL1, float PLL2, int user_num, int bitnum_per, int N_samp, Ipp32fc* x_zheng)
{
    int n = channel_num * n1 + n2;  // 总权重向量长度
    int output_length = user_num / bitnum_per;  // 修改：输出长度为user_num/bitnum_per

    // 将单精度输入转换为双精度（临时变量）
    Ipp64fc* sympol_64f = ippsMalloc_64fc(N_samp);
    Ipp64fc* reflection_64f = ippsMalloc_64fc(reflection_size);
    Ipp64fc* out_frac_64f = ippsMalloc_64fc(out_frac_length);
    //OutputDebugString(L"始调用MDFE_HX_64f第一个循环");
    for (int i = 0; i < N_samp; i++) {
        sympol_64f[i].re = (double)sympol[i].re;
        sympol_64f[i].im = (double)sympol[i].im;
    }
   // OutputDebugString(L"始调用MDFE_HX_64f第二个循环");

    for (int i = 0; i < reflection_size; i++) {
        reflection_64f[i].re = (double)reflection[i].re;
        reflection_64f[i].im = (double)reflection[i].im;
    }
    for (int i = 0; i < out_frac_length; i++) {
        out_frac_64f[i].re = (double)out_frac[i].re;
        out_frac_64f[i].im = (double)out_frac[i].im;
    }

    // 分配双精度内存
    Ipp64fc* w_ff = ippsMalloc_64fc(channel_num * n1);
    ippsZero_64fc(w_ff, channel_num * n1);

    Ipp64fc* w_fb = ippsMalloc_64fc(n2);
    ippsZero_64fc(w_fb, n2);

    Ipp64fc* w = ippsMalloc_64fc(n);
    ippsZero_64fc(w, n);

    Ipp64fc* P = ippsMalloc_64fc(n * n);  // 相关矩阵
    ippsZero_64fc(P, n * n);
    // 初始化P为Delta*I
   // OutputDebugString(L"始调用MDFE_HX_64f第三个循环");

    for (int i = 0; i < n; i++) {
        P[i * n + i].re = (double)Delta;
        P[i * n + i].im = 0.0;
    }

    Ipp64fc* e_zheng = ippsMalloc_64fc(output_length);
    ippsZero_64fc(e_zheng, output_length);

    Ipp64fc* NCO_Phase = ippsMalloc_64fc(channel_num * (output_length - n1));
    ippsZero_64fc(NCO_Phase, channel_num * (output_length - n1));

    Ipp64f* Discriminator_Out = ippsMalloc_64f(channel_num * (output_length - n1));
    ippsZero_64f(Discriminator_Out, channel_num * (output_length - n1));

    // 新增：决策符号数组（双精度）
    Ipp64fc* decision_symbol = ippsMalloc_64fc(output_length);
    ippsZero_64fc(decision_symbol, output_length);
    // 初始化前N_samp个决策符号为训练序列
    //OutputDebugString(L"始调用MDFE_HX_64f第四个循环");

    for (int i = 0; i < N_samp; i++) {
        decision_symbol[i] = sympol_64f[i];
    }

    Ipp64fc* y = ippsMalloc_64fc(channel_num * n1);
    ippsZero_64fc(y, channel_num * n1);

    Ipp64fc* pn = ippsMalloc_64fc(channel_num);
    Ipp64fc* u = ippsMalloc_64fc(n);
    Ipp64fc* y_back = ippsMalloc_64fc(n2);
    Ipp64fc* K = ippsMalloc_64fc(n);

    // 双精度版本的x_zheng
    Ipp64fc* x_zheng_64f = ippsMalloc_64fc(output_length);
    ippsZero_64fc(x_zheng_64f, output_length);

    wchar_t tempBuf[256];
    swprintf_s(tempBuf, L"T始调用MDFE_HX_64f第五个超级大循环,进入循环前，N_samp值: %d，channel_num值：%d,n1值：%d,n2值：%d", N_samp,channel_num,n1,n2);
    OutputDebugString(tempBuf);

    // 训练序列部分
    for (int i = 2 * n2 + 1; i < 2 * N_samp + 1; i++) {
        ippsZero_64fc(u, n);
        int num = i / 2;

        for (int count = 0; count < channel_num; count++) {
            // 更新前馈滤波器权重
            ippsCopy_64fc(w + count * n1, w_ff + count * n1, n1);

            // 应用NCO相位校正
            for (int j = 0; j < n1; j++) {
                int idx = i + n1 - 1 - j;
                if (num > 1 && idx < out_frac_length) {  // 修改：防止NCO_Phase越界
                    // 计算NCO相位
                    double phase = fmod(NCO_Phase[count * (output_length - n1) + num - 2].re, 2 * IPP_PI);
                    Ipp64fc phase_rotation = { cos(-phase), sin(-phase) };
                    // 计算一维数组中的索引
                    int linear_idx = idx - 1 + (out_frac_length / channel_num) * count;
                    Ipp64fc temp;
                    ippsMul_64fc(&out_frac_64f[linear_idx], &phase_rotation, &temp, 1);
                    y[count * n1 + j] = temp;
                }
                else {
                    y[count * n1 + j].re = 0.0;
                    y[count * n1 + j].im = 0.0;
                }
            }
        }

        ippsCopy_64fc(w + channel_num * n1, w_fb, n2);

        if (i % 2 == 0) {  // 每2个采样点处理一次
            // 准备反馈滤波器输入
            for (int j = 0; j < n2; j++) {
                int idx = num - 1 - j - 1;
                if (idx >= 0 && idx < output_length) {
                    y_back[j] = sympol_64f[idx];
                }
                else {
                    y_back[j].re = 0.0;
                    y_back[j].im = 0.0;
                }
            }

            // 计算前馈和反馈输出，组合输入向量
            for (int count = 0; count < channel_num; count++) {
                Ipp64fc dotProduct = { 0.0, 0.0 };

                // 创建临时数组来存储w_ff的共轭
                Ipp64fc* w_ff_conj = ippsMalloc_64fc(n1);
                ippsConj_64fc(w_ff + count * n1, w_ff_conj, n1);
                ippsDotProd_64fc(w_ff_conj, y + count * n1, n1, &dotProduct);
                ippsFree(w_ff_conj);

                pn[count] = dotProduct;
                ippsCopy_64fc(y + count * n1, u + count * n1, n1);
            }

            // 设置输入向量u的反馈部分
            ippsCopy_64fc(y_back, u + channel_num * n1, n2);

            // 计算均衡器输出
            Ipp64fc* w_conj = ippsMalloc_64fc(n);
            ippsConj_64fc(w, w_conj, n);
            Ipp64fc dotProduct = { 0.0, 0.0 };
            ippsDotProd_64fc(w_conj, u, n, &dotProduct);
            x_zheng_64f[num - 1] = dotProduct;
            ippsFree(w_conj);

            // 计算误差
            e_zheng[num - 1].re = sympol_64f[num - 1].re - x_zheng_64f[num - 1].re;
            e_zheng[num - 1].im = sympol_64f[num - 1].im - x_zheng_64f[num - 1].im;

            // 计算增益向量K（双精度）
            CalcGainVector_64f(P, u, (double)Lambda, n, K);

            // 更新相关矩阵P（双精度）
            UpdateCorrelationMatrix_MKL_64f(P, K, u, (double)Lambda, n);

            // 创建 e_zheng[num - 1] 的共轭
            Ipp64fc e_zheng_conj = { e_zheng[num - 1].re, -e_zheng[num - 1].im };

            // 更新权重向量w
            UpdateWeights_64f(w, K, e_zheng_conj, n);


   /*         wchar_t tempBuf2[256];
            swprintf_s(tempBuf, L"进入更新锁相环参数循环，当前循环i值: %d", i);
            OutputDebugString(tempBuf);*/
            // 更新锁相环参数
            for (int count = 0; count < channel_num; count++) {
                Ipp64fc error_plus_pn_conj = { e_zheng[num - 1].re + pn[count].re, -e_zheng[num - 1].im - pn[count].im };
                Ipp64fc disc_complex;
                Ipp64fc disc_complex_ln;
                ippsMul_64fc(&pn[count], &error_plus_pn_conj, &disc_complex, 1);
                ippsLn_64fc_A26(&disc_complex, &disc_complex_ln, 1);
                Discriminator_Out[count * (output_length - n1) + num - 1] = disc_complex_ln.im;
                if (num >= 2) {
                    NCO_Phase[count * (output_length - n1) + num - 1].re =
                        2 * NCO_Phase[count * (output_length - n1) + num - 2].re -
                        NCO_Phase[count * (output_length - n1) + num - 3].re +
                        (double)PLL1 * Discriminator_Out[count * (output_length - n1) + num - 1] -
                        (double)PLL2 * Discriminator_Out[count * (output_length - n1) + num - 2];
                    NCO_Phase[count * (output_length - n1) + num - 1].im = 0.0;
                }
            }
        }
    }

    wchar_t tempBuf2[256];
    swprintf_s(tempBuf, L"开始调用MDFE_HX_64f第六个超级大循环，进入循环前，output_length值: %d", output_length);
    OutputDebugString(tempBuf);

    // 符号均衡部分
    for (int i = 2 * N_samp + 1; i < 2 * (output_length - n1) + 1; i++) {  // 修改：循环边界
        ippsZero_64fc(u, n);
        int num = i / 2;

        for (int count = 0; count < channel_num; count++) {
            // 更新前馈滤波器权重
            ippsCopy_64fc(w + count * n1, w_ff + count * n1, n1);

            // 应用NCO相位校正
            for (int j = 0; j < n1; j++) {
                int idx = i + n1 - 1 - j;
                if (num > 1 && idx < out_frac_length) {
                    // 计算NCO相位
                    double phase = fmod(NCO_Phase[count * (output_length - n1) + num - 2].re, 2 * IPP_PI);
                    Ipp64fc phase_rotation = { cos(-phase), sin(-phase) };
                    // 计算一维数组中的索引
                    int linear_idx = idx - 1 + (out_frac_length / channel_num) * count;
                    Ipp64fc temp;
                    ippsMul_64fc(&out_frac_64f[linear_idx], &phase_rotation, &temp, 1);
                    y[count * n1 + j] = temp;
                }
                else {
                    y[count * n1 + j].re = 0.0;
                    y[count * n1 + j].im = 0.0;
                }
            }
        }

        ippsCopy_64fc(w + channel_num * n1, w_fb, n2);

        if (i % 2 == 0) {  // 每2个采样点处理一次
            // 准备反馈滤波器输入 - 修改：使用decision_symbol
            for (int j = 0; j < n2; j++) {
                int idx = num - 1 - j - 1;
                if (idx >= 0 && idx < output_length) {
                    y_back[j] = decision_symbol[idx];
                }
                else {
                    y_back[j].re = 0.0;
                    y_back[j].im = 0.0;
                }
            }

            // 计算前馈和反馈输出，组合输入向量
            for (int count = 0; count < channel_num; count++) {
                Ipp64fc dotProduct = { 0.0, 0.0 };

                // 创建临时数组来存储w_ff的共轭
                Ipp64fc* w_ff_conj = ippsMalloc_64fc(n1);
                ippsConj_64fc(w_ff + count * n1, w_ff_conj, n1);
                ippsDotProd_64fc(w_ff_conj, y + count * n1, n1, &dotProduct);
                ippsFree(w_ff_conj);

                pn[count] = dotProduct;
                ippsCopy_64fc(y + count * n1, u + count * n1, n1);
            }

            // 设置输入向量u的反馈部分
            ippsCopy_64fc(y_back, u + channel_num * n1, n2);

            // 计算均衡器输出
            Ipp64fc* w_conj = ippsMalloc_64fc(n);
            ippsConj_64fc(w, w_conj, n);
            Ipp64fc dotProduct = { 0.0, 0.0 };
            ippsDotProd_64fc(w_conj, u, n, &dotProduct);
            x_zheng_64f[num - 1] = dotProduct;
            ippsFree(w_conj);

            // 使用硬判决函数
            Ipp64fc temp_decision;
            HardDecision_64f(1, &x_zheng_64f[num - 1], reflection_64f, reflection_size, &temp_decision);

            decision_symbol[num - 1] = temp_decision;  // 新增：存储决策符号

            // 计算误差
            e_zheng[num - 1].re = temp_decision.re - x_zheng_64f[num - 1].re;
            e_zheng[num - 1].im = temp_decision.im - x_zheng_64f[num - 1].im;

            // 计算增益向量K（双精度）
            CalcGainVector_64f(P, u, (double)Lambda, n, K);

            // 更新相关矩阵P（双精度）
            UpdateCorrelationMatrix_MKL_64f(P, K, u, (double)Lambda, n);

            // 创建 e_zheng[num - 1] 的共轭
            Ipp64fc e_zheng_conj = { e_zheng[num - 1].re, -e_zheng[num - 1].im };

            // 更新权重向量w
            UpdateWeights_64f(w, K, e_zheng_conj, n);


           
            // 更新锁相环参数
            for (int count = 0; count < channel_num; count++) {
                Ipp64fc error_plus_pn_conj = { e_zheng[num - 1].re + pn[count].re, -e_zheng[num - 1].im - pn[count].im };
                Ipp64fc disc_complex;
                Ipp64fc disc_complex_ln;
                ippsMul_64fc(&pn[count], &error_plus_pn_conj, &disc_complex, 1);
                ippsLn_64fc_A26(&disc_complex, &disc_complex_ln, 1);
                Discriminator_Out[count * (output_length - n1) + num - 1] = disc_complex_ln.im;
                if (num >= 2) {
                    NCO_Phase[count * (output_length - n1) + num - 1].re =
                        2 * NCO_Phase[count * (output_length - n1) + num - 2].re -
                        NCO_Phase[count * (output_length - n1) + num - 3].re +
                        (double)PLL1 * Discriminator_Out[count * (output_length - n1) + num - 1] -
                        (double)PLL2 * Discriminator_Out[count * (output_length - n1) + num - 2];
                    NCO_Phase[count * (output_length - n1) + num - 1].im = 0.0;
                }
            }
        }
    }
    OutputDebugString(L"始调用MDFE_HX_64f第七个循环");

    // 将双精度结果转换回单精度输出
    for (int i = 0; i < output_length; i++) {
        x_zheng[i].re = (float)x_zheng_64f[i].re;
        x_zheng[i].im = (float)x_zheng_64f[i].im;
    }

    // 释放临时双精度输入内存
    ippsFree(sympol_64f);
    ippsFree(reflection_64f);
    ippsFree(out_frac_64f);

    // 释放双精度内存
    ippsFree(w_ff);
    ippsFree(w_fb);
    ippsFree(w);
    ippsFree(P);
    ippsFree(e_zheng);
    ippsFree(NCO_Phase);
    ippsFree(Discriminator_Out);
    ippsFree(decision_symbol);
    ippsFree(y);
    ippsFree(pn);
    ippsFree(u);
    ippsFree(y_back);
    ippsFree(K);
    ippsFree(x_zheng_64f);
}




void Delete_Data_Equ_N_Samp(Ipp32fc* Signal_DataEqu, Ipp32fc* Signal_DataEqu_Out, Ipp32s va_g_Syn_NFFT, Ipp32s va_N_g, Ipp32s va_g_N_Block, Ipp32s va_N_samp_SIMO)
{
    for (int i = 0; i < va_g_N_Block; i++)
    {
        ippsCopy_32fc(Signal_DataEqu + i * (va_g_Syn_NFFT - va_N_g) + va_N_samp_SIMO, Signal_DataEqu_Out + i * ((va_g_Syn_NFFT - va_N_g) - va_N_samp_SIMO), (va_g_Syn_NFFT - va_N_g) - va_N_samp_SIMO);
    }
}

void TDE_Syn(Ipp32u MaxCacheFrameCnt, Ipp8u* pSyn_StepCnt, Ipp8u* pSyn_DataCacheCnt, Ipp32fc* Syn_DataCache, Ipp32fc* Syn_DataCachePrmy, Ipp32fc* Sig_blk, Ipp32f* Syn_SigIn, Ipp32s Syn_SigLen, Ipp32fc* Syn_FIRCoe, Ipp32s Syn_FIRLen, Ipp32fc* Syn_RefCopySam, Ipp32fc* Syn_RefCopyAll, Ipp8u* Syn_Flag, Ipp32f* Syn_SigRec, Ipp32f g_Syn_Threshold)
{
    Ipp16u MaxNum = 0;
    MaxNum = MaxCacheFrameCnt;

    Ipp32fc* BaseBandSig = ippsMalloc_32fc(TDE_g_Syn_BufCnt);
    ippsZero_32fc(BaseBandSig, TDE_g_Syn_BufCnt);
    if (*pSyn_StepCnt == 0) //粗同步阶段
    {
        //初始化
        Ipp32s Syn_PosFirst = -1;
        Ipp8u Syn_FlagFirst = 0;
        //Step1 对实时接收到的6144点信号做降采样和滤波,输出基带的6144点信号

        //DownConversion(Syn_SigIn, Syn_SigLen, Syn_FIRCoe, Syn_FIRLen, BaseBandSig);
        Rev2Cpl_SC(Syn_SigIn, Syn_SigLen, BaseBandSig);
        //Step2 对基带的6144点信号做一次粗同步,输出同步结果和2048点的检测向量Sig_blk
        SynStep1_SC_Edited(Syn_SigIn, BaseBandSig, TDE_g_Syn_BufCnt, Syn_RefCopySam, Sig_blk, Syn_DataCache, Syn_DataCachePrmy, &Syn_PosFirst, &Syn_FlagFirst, Syn_Threshold, TDE_g_Syn_NFFT_RAW, TDE_g_Syn_BufSamCnt, TDE_g_Syn_BufCnt, TDE_g_SamStep);

        if (Syn_FlagFirst == 1)
        {
            *pSyn_StepCnt = 1;
        }
    }
    else if (*pSyn_StepCnt == 1)//缓存阶段
    {
        if (*pSyn_DataCacheCnt == MaxCacheFrameCnt)
        {
            *pSyn_StepCnt = 2;//进入细同步的标志位置位
        }
        else
        {
            Ipp32fc* Syn_SigInCplx = ippsMalloc_32fc(TDE_g_Syn_BufCnt);
            Rev2Cpl_SC(Syn_SigIn, TDE_g_Syn_BufCnt, Syn_SigInCplx);
            ippsCopy_32fc(Syn_SigInCplx, Syn_DataCache + TDE_g_Syn_BufCnt * 2 + (*pSyn_DataCacheCnt) * TDE_g_Syn_BufCnt, TDE_g_Syn_BufCnt);
            ippsCopy_32fc(Syn_SigInCplx, Syn_DataCachePrmy + TDE_g_Syn_BufCnt * 2 + (*pSyn_DataCacheCnt) * TDE_g_Syn_BufCnt, TDE_g_Syn_BufCnt);
            (*pSyn_DataCacheCnt)++;
            ippsFree(Syn_SigInCplx);

        }
    }
    else if (*pSyn_StepCnt == 2)//细同步阶段
    {

        Ipp32s Syn_PosSecond = -1;
        //SynStep2_SC(Syn_DataCache, Syn_DataCachePrmy, Syn_RefCopyAll, &Syn_PosSecond, Syn_SigRec);


        Ipp32f* Syn_DataCachePrmy_Real = ippsMalloc_32f(TDE_Signal_After_BP_lenth + TDE_g_LFM2Data_lenth * 2);
        Ipp32f* Syn_RefCopyAll_Real = ippsMalloc_32f(TDE_g_LFM2Data_lenth);
        //Ipp32f* Syn_SigRec_Real = ippsMalloc_32f(g_InfoSamPointTotalSyn);


        Cpl2Rev_SC(Syn_DataCachePrmy, TDE_Signal_After_BP_lenth + TDE_g_LFM2Data_lenth * 2, Syn_DataCachePrmy_Real);
        Cpl2Rev_SC(TDE_SignalHFM, TDE_g_LFM2Data_lenth, Syn_RefCopyAll_Real);

        Sync_SC_Edited(Syn_DataCachePrmy_Real, Syn_RefCopyAll_Real,
            &Syn_PosSecond, Syn_SigRec, TDE_Signal_After_BP_lenth, TDE_g_LFM2Data_lenth, TDE_g_InfoSamPointTotalSyn, TDE_g_fs, TDE_DelayLen);


        *Syn_Flag = 1;//同步成功标志位置位
    }
    else
    {
        printf("同步错误，请检查参数 *pSyn_StepCnt");
    }

    ippsFree(BaseBandSig);
}

void Sync_SC_Edited(Ipp32f* Syn_DataCachePrmy, Ipp32f* Syn_RefCopyAll, Ipp32s* Syn_PosSecond, Ipp32f* Syn_SigRec, Ipp32s va_Signal_After_BP_lenth, Ipp32s va_g_LFM2Data_lenth, Ipp32s va_g_InfoSamPointTotalSyn, Ipp32s va_g_fs, Ipp32s va_DelayLen)
{


    //IppEnum funCfg = (IppEnum)(ippAlgDirect);
    IppEnum funCfgNormA = (IppEnum)(ippAlgFFT | ippsNormA);
    int bufSize;

    int lowLag = -((va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) - 1);
    ippsCrossCorrNormGetBufferSize((va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2), (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2), 2 * (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) - 1, lowLag, ipp32f, funCfgNormA, &bufSize);
    Ipp8u* pBuffer = ippsMalloc_8u(bufSize);


    Ipp32f* Syn_RefCopyAll_Padded = ippsMalloc_32f((va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2));
    ippsZero_32f(Syn_RefCopyAll_Padded, (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2));
    ippsCopy_32f(Syn_RefCopyAll, Syn_RefCopyAll_Padded, va_g_LFM2Data_lenth);

    //初始化同步标志和位置
    Ipp32f* Syn2_CorrCur = ippsMalloc_32f(2 * (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) - 1);
    Ipp32f* Syn2_CorrCur_Padded = ippsMalloc_32f((va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) + va_g_LFM2Data_lenth - 1);
    Ipp32f* Syn2_CorrCur_Abs = ippsMalloc_32f((va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) + va_g_LFM2Data_lenth - 1);

    //ippsConvolve_32f(
    //    Syn_DataCachePrmy,  // 输入信号 x[m]
    //    (Signal_After_BP_lenth + g_LFM2Data_lenth *2),// 信号 x 的长度
    //    Syn_RefCopyAll,  // 输入信号 y[m]
    //    g_LFM2Data_lenth,   // 信号 y 的长度
    //    Syn2_CorrCur,         // 输出结果 Rxy[n]
    //    funCfg,
    //    pBuffer
    //);

    ippsCrossCorrNorm_32f(
        Syn_RefCopyAll_Padded,// 输入信号 x[m]
        (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2),// 信号 x 的长度
        Syn_DataCachePrmy,  // 输入信号 y[m]
        (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2),   // 信号 y 的长度
        Syn2_CorrCur,         // 输出结果 Rxy[n]
        2 * (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) - 1,
        lowLag,
        funCfgNormA,
        pBuffer

    );


    ippsCopy_32f(Syn2_CorrCur + (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) - va_g_LFM2Data_lenth, Syn2_CorrCur_Padded, (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) + va_g_LFM2Data_lenth - 1);


    ippsAbs_32f(Syn2_CorrCur_Padded, Syn2_CorrCur_Abs, (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) + va_g_LFM2Data_lenth - 1);
    //找到相关值最大的位置，截取信号
    Ipp32f MaxAbsCur = 0;
    ippsMaxAbsIndx_32f(Syn2_CorrCur_Abs, va_g_fs, &MaxAbsCur, Syn_PosSecond);
    *Syn_PosSecond = *Syn_PosSecond + 1;

    //截取信号,是从原始信号的缓存数组里截取的
    ippsCopy_32f(Syn_DataCachePrmy + *Syn_PosSecond + va_DelayLen * 2, Syn_SigRec, va_g_InfoSamPointTotalSyn);

    Ipp32f maxAbsValue = 0;
    ippsMaxAbs_32f(Syn_SigRec, va_g_InfoSamPointTotalSyn, &maxAbsValue);
    // 对 Syn_SigRec 进行归一化
    if (maxAbsValue > 0) { // 防止除以 0
        ippsNormalize_32f(Syn_SigRec, Syn_SigRec, va_g_InfoSamPointTotalSyn, 0, maxAbsValue);
    }
    //释放内存
    ippsFree(Syn2_CorrCur);
    ippsFree(Syn2_CorrCur_Abs);
    ippsFree(pBuffer);
}

void MASS_Sync_SC_Edited(Ipp32f* Syn_DataCachePrmy, Ipp32f* Syn_RefCopyAll, Ipp32s* Syn_PosSecond, Ipp32f* Syn_SigRec, Ipp32s va_Signal_After_BP_lenth, Ipp32s va_g_LFM2Data_lenth, Ipp32s va_g_InfoSamPointTotalSyn, Ipp32s va_g_fs, Ipp32s va_DelayLen, Ipp32f* Channel_Length, Ipp32f* Syn2_CorrCur_Padded_Copy)
{
    //IppEnum funCfg = (IppEnum)(ippAlgDirect);
    IppEnum funCfgNormA = (IppEnum)(ippAlgFFT | ippsNormA);
    int bufSize;

    int lowLag = -((va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) - 1);
    ippsCrossCorrNormGetBufferSize((va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2), (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2), 2 * (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) - 1, lowLag, ipp32f, funCfgNormA, &bufSize);
    Ipp8u* pBuffer = ippsMalloc_8u(bufSize);


    Ipp32f* Syn_RefCopyAll_Padded = ippsMalloc_32f((va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2));
    ippsZero_32f(Syn_RefCopyAll_Padded, (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2));
    ippsCopy_32f(Syn_RefCopyAll, Syn_RefCopyAll_Padded, va_g_LFM2Data_lenth);

    //初始化同步标志和位置
    Ipp32f* Syn2_CorrCur = ippsMalloc_32f(2 * (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) - 1);
    Ipp32f* Syn2_CorrCur_Padded = ippsMalloc_32f((va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) + va_g_LFM2Data_lenth - 1);
    Ipp32f* Syn2_CorrCur_Abs = ippsMalloc_32f((va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) + va_g_LFM2Data_lenth - 1);

    //ippsConvolve_32f(
    //    Syn_DataCachePrmy,  // 输入信号 x[m]
    //    (Signal_After_BP_lenth + g_LFM2Data_lenth *2),// 信号 x 的长度
    //    Syn_RefCopyAll,  // 输入信号 y[m]
    //    g_LFM2Data_lenth,   // 信号 y 的长度
    //    Syn2_CorrCur,         // 输出结果 Rxy[n]
    //    funCfg,
    //    pBuffer
    //);

    ippsCrossCorrNorm_32f(
        Syn_RefCopyAll_Padded,// 输入信号 x[m]
        (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2),// 信号 x 的长度
        Syn_DataCachePrmy,  // 输入信号 y[m]
        (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2),   // 信号 y 的长度
        Syn2_CorrCur,         // 输出结果 Rxy[n]
        2 * (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) - 1,
        lowLag,
        funCfgNormA,
        pBuffer

    );


    ippsCopy_32f(Syn2_CorrCur + (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) - va_g_LFM2Data_lenth, Syn2_CorrCur_Padded, (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) + va_g_LFM2Data_lenth - 1);


    ippsAbs_32f(Syn2_CorrCur_Padded, Syn2_CorrCur_Abs, (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) + va_g_LFM2Data_lenth - 1);
    //找到相关值最大的位置，截取信号
    Ipp32f MaxAbsCur = 0;
    ippsMaxAbsIndx_32f(Syn2_CorrCur_Abs, va_g_fs, &MaxAbsCur, Syn_PosSecond);
    *Syn_PosSecond = *Syn_PosSecond + 1;




    // ==================== 新增的MATLAB代码对应的IPP实现 ====================

// 1. index = find(abs(SigCorr)<MaxValue/10);
// 2. SigCorr(index) = 0;
// 计算阈值 MaxValue/10
    Ipp32f threshold = MaxAbsCur / 10.0f;
    int corrLength = (va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) + va_g_LFM2Data_lenth - 1;

    // 将小于阈值的相关值置零
    for (int i = 0; i < corrLength; i++) {
        if (Syn2_CorrCur_Abs[i] < threshold) {
            Syn2_CorrCur_Padded[i] = 0.0f;
        }
    }
    ippsCopy_32f(Syn2_CorrCur_Padded, Syn2_CorrCur_Padded_Copy,(va_Signal_After_BP_lenth + va_g_LFM2Data_lenth * 2) + va_g_LFM2Data_lenth - 1);
    // 3. ChannelUncasual = SigCorr(Pose-1*g_fs: Pose);
    // 4. ChannelCasual = SigCorr(Pose: Pose+2*g_fs);
    // 分配内存用于存储通道数据
    Ipp32f* ChannelUncasual = ippsMalloc_32f(va_g_fs + 1);  // Pose-g_fs 到 Pose，共 g_fs+1 个点
    Ipp32f* ChannelCasual = ippsMalloc_32f(2 * va_g_fs + 1); // Pose 到 Pose+2*g_fs，共 2*g_fs+1 个点
    Ipp32fc* ChannelUncasual_Cplx = ippsMalloc_32fc(va_g_fs + 1);  // Pose-g_fs 到 Pose，共 g_fs+1 个点
    Ipp32fc* ChannelCasual_Cplx = ippsMalloc_32fc(2 * va_g_fs + 1); // Pose 到 Pose+2*g_fs，共 2*g_fs+1 个点
    // 确保索引不越界
    int pose = *Syn_PosSecond - 1; // 转换为0基索引
    int casual_start = pose;
    int casual_end = pose + 2 * va_g_fs;
    // 边界检查和数据复制
    ippsCopy_32f(Syn2_CorrCur_Padded, ChannelUncasual, pose);
    int casual_len = casual_end - casual_start + 1;
    if (casual_len > 0) {
            ippsCopy_32f(Syn2_CorrCur_Padded + casual_start, ChannelCasual, casual_len);
    }

    Ipp32f RmsDelayUncasual = 0.0f;
    Ipp32f RmsDelayCasual = 0.0f;


    Ipp32f Tb = MA_g_fs;
    Rev2Cpl_SC(ChannelUncasual, pose, ChannelUncasual_Cplx);
    Rev2Cpl_SC(ChannelCasual, casual_len, ChannelCasual_Cplx);


    RmsDelayUncasual = computeRMSDelay(ChannelUncasual_Cplx, pose, 1/Tb);
    RmsDelayCasual = computeRMSDelay(ChannelCasual_Cplx, casual_len, 1/Tb);
    *Channel_Length = RmsDelayUncasual + RmsDelayCasual;

    ippsFree(ChannelUncasual);
    ippsFree(ChannelCasual);
    ippsFree(ChannelUncasual_Cplx);
    ippsFree(ChannelCasual_Cplx);



    //截取信号,是从原始信号的缓存数组里截取的
    ippsCopy_32f(Syn_DataCachePrmy + *Syn_PosSecond + va_DelayLen * 2, Syn_SigRec, va_g_InfoSamPointTotalSyn);

    Ipp32f maxAbsValue = 0;
    ippsMaxAbs_32f(Syn_SigRec, va_g_InfoSamPointTotalSyn, &maxAbsValue);
    // 对 Syn_SigRec 进行归一化
    if (maxAbsValue > 0) { // 防止除以 0
        ippsNormalize_32f(Syn_SigRec, Syn_SigRec, va_g_InfoSamPointTotalSyn, 0, maxAbsValue);
    }
    //释放内存
    ippsFree(Syn2_CorrCur);
    ippsFree(Syn2_CorrCur_Abs);
    ippsFree(pBuffer);

}

void DownConversion_TDE(Ipp32f* Syn_SigIn, Ipp32s Syn_SigLen, Ipp32fc* Syn_FIRCoe, Ipp32s Syn_FIRLen, Ipp32fc* DownSampledSig)
{
    //申请内存
    Ipp32u SigCnt = 0, delay = 0;
    Ipp32fc* MixSig = ippsMalloc_32fc(Syn_SigLen + Syn_FIRLen - 1);
    Ipp32fc* MixSigFIR = ippsMalloc_32fc(Syn_SigLen + Syn_FIRLen - 1);
    ippsZero_32fc(MixSig, Syn_SigLen + Syn_FIRLen - 1);
    ippsZero_32fc(MixSigFIR, Syn_SigLen + Syn_FIRLen - 1);

    /// Section 1: 调制到基带
    Ipp32f* VectorInt = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* SinVectorInt = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* CosVectorInt = ippsMalloc_32f(Syn_SigLen);

    Ipp32f* SigSin = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* SigCos = ippsMalloc_32f(Syn_SigLen);

    for (SigCnt = 0; SigCnt < Syn_SigLen; SigCnt++)
    {
        *(VectorInt + SigCnt) = (Ipp32f)(-2 * IPP_PI * TDE_g_f0 * SigCnt / TDE_g_fs);
    }
    //生成正弦和余弦
    ippsSin_32f_A11(VectorInt, SinVectorInt, Syn_SigLen);
    ippsMul_32f(Syn_SigIn, SinVectorInt, SigSin, Syn_SigLen);
    ippsCos_32f_A11(VectorInt, CosVectorInt, Syn_SigLen);
    ippsMul_32f(Syn_SigIn, CosVectorInt, SigCos, Syn_SigLen);

    //组合成复数信号
    ippsRealToCplx_32f(SigCos, SigSin, MixSig, Syn_SigLen);




    Ipp32fc* filteredSignal = (Ipp32fc*)ippsMalloc_32fc(Syn_SigLen + Syn_FIRLen); // 分配内存用于存储滤波结果


    SC_FIR(MixSig, Syn_SigLen + ((Syn_FIRLen - 1) / 2), Syn_FIRCoe, Syn_FIRLen, filteredSignal); // FIR 滤波，这个测试了没问题

    Ipp32fc* OutputSignal = (Ipp32fc*)ippsMalloc_32fc(Syn_SigLen);   // 分配内存用于最终输出

    delay = (Syn_FIRLen - 1);
    ippsCopy_32fc(filteredSignal + delay / 2, OutputSignal, Syn_SigLen); // 裁剪延迟




    /// Section 2: 实现降采样
    Ipp32s LengthOutSignal = Syn_SigLen;      // 滤波后的信号长度
    Ipp32s LengthAftDown = LengthOutSignal / (TDE_N_upsample / 2); // 降采样后的信号长度

    for (Ipp32s i = 0; i < LengthAftDown && i * (TDE_N_upsample / 2) < LengthOutSignal; i++) {
        DownSampledSig[i].re = 2 * OutputSignal[i * (TDE_N_upsample / 2)].re; // 实部乘以 2

        //此处翻转一下DownSampledSig_1的虚部

        DownSampledSig[i].im = -2 * OutputSignal[i * (TDE_N_upsample / 2)].im; // 虚部乘以 2
    }



    //释放内存
    ippsFree(MixSig);
    ippsFree(MixSigFIR);
    ippsFree(VectorInt);
    ippsFree(SinVectorInt);
    ippsFree(CosVectorInt);
    ippsFree(SigSin);
    ippsFree(SigCos);
}

Ipp32f computeRMSDelay(const Ipp32fc* h, int h_length, Ipp32f Tb)
{
    // 输入参数检查
    if (h == nullptr || h_length <= 0 || Tb <= 0) {
        printf("错误：输入参数无效\n");
        return -1.0f;
    }

    // 分配内存
    Ipp32f* P = ippsMalloc_32f(h_length);           // 功率时延分布
    Ipp32f* t = ippsMalloc_32f(h_length);           // 时延向量
    Ipp32f* temp1 = ippsMalloc_32f(h_length);      // 临时数组1
    Ipp32f* temp2 = ippsMalloc_32f(h_length);      // 临时数组2

    // 1. 计算功率时延分布
    ippsPowerSpectr_32fc(h, P, h_length);

    // 2. 归一化功率
    Ipp32f sum_P;
    ippsSum_32f(P, h_length, &sum_P, ippAlgHintFast);

    if (sum_P <= 0.0f) {
        printf("错误：功率总和为零或负值\n");
        ippsFree(P);
        ippsFree(t);
        ippsFree(temp1);
        ippsFree(temp2);
        return -1.0f;
    }

    ippsDivC_32f_I(sum_P, P, h_length); // 就地归一化

    // 3. 生成时延向量并计算加权均值
    // 使用线性插值生成等间距序列
    ippsVectorSlope_32f(t, h_length, 0.0f, Tb);

    // 4. 计算 tau_mean = sum(P .* t)
    ippsMul_32f(P, t, temp1, h_length);
    Ipp32f tau_mean;
    ippsSum_32f(temp1, h_length, &tau_mean, ippAlgHintFast);

    // 5. 计算 tau_squared_mean = sum(P .* t.^2)
    ippsSqr_32f(t, temp2, h_length);        // t.^2
    ippsMul_32f(P, temp2, temp1, h_length); // P .* t.^2
    Ipp32f tau_squared_mean;
    ippsSum_32f(temp1, h_length, &tau_squared_mean, ippAlgHintFast);

    // 6. 计算方差和RMS时延扩展
    Ipp32f variance = tau_squared_mean - tau_mean * tau_mean;
    if (variance < 0.0f) {
        variance = 0.0f; // 修正数值误差
    }

    Ipp32f rms_delay = sqrt(variance);

    // 释放内存
    ippsFree(P);
    ippsFree(t);
    ippsFree(temp1);
    ippsFree(temp2);

    return rms_delay;
}

float calculateBER_IPP(const char* originalBits, const char* receivedBits, int length)
{
    if (originalBits == nullptr || receivedBits == nullptr || length <= 0) {
        std::cout << "错误：输入参数无效！" << std::endl;
        return -1.0;
    }

    // 分配IPP内存用于存储Ipp8u类型数据
    Ipp8u* original_ipp = ippsMalloc_8u(length);
    Ipp8u* received_ipp = ippsMalloc_8u(length);
    Ipp8u* xor_result = ippsMalloc_8u(length);

    if (original_ipp == nullptr || received_ipp == nullptr || xor_result == nullptr) {
        std::cout << "错误：内存分配失败！" << std::endl;
        // 释放已分配的内存
        if (original_ipp) ippsFree(original_ipp);
        if (received_ipp) ippsFree(received_ipp);
        if (xor_result) ippsFree(xor_result);
        return -1.0;
    }

    // 将char*转换为Ipp8u*（只保留最低位，即0或1）
    for (int i = 0; i < length; i++) {
        original_ipp[i] = (Ipp8u)(originalBits[i] & 0x01);  // 确保只取最低位
        received_ipp[i] = (Ipp8u)(receivedBits[i] & 0x01);  // 确保只取最低位
    }

    // 使用IPP的XOR函数计算异或结果
    IppStatus status = ippsXor_8u(original_ipp, received_ipp, xor_result, length);

    if (status != ippStsNoErr) {
        std::cout << "错误：IPP XOR运算失败，错误代码：" << status << std::endl;
        ippsFree(original_ipp);
        ippsFree(received_ipp);
        ippsFree(xor_result);
        return -1.0;
    }

    // 将8u数据转换为32f以便使用IPP求和函数
    Ipp32f* xor_result_32f = ippsMalloc_32f(length);
    if (xor_result_32f == nullptr) {
        std::cout << "错误：内存分配失败！" << std::endl;
        ippsFree(original_ipp);
        ippsFree(received_ipp);
        ippsFree(xor_result);
        return -1.0;
    }

    // 将8u转换为32f
    IppStatus convert_status = ippsConvert_8u32f(xor_result, xor_result_32f, length);
    if (convert_status != ippStsNoErr) {
        std::cout << "错误：数据类型转换失败，错误代码：" << convert_status << std::endl;
        ippsFree(original_ipp);
        ippsFree(received_ipp);
        ippsFree(xor_result);
        ippsFree(xor_result_32f);
        return -1.0;
    }

    // 使用IPP求和函数统计错误比特数
    Ipp32f errorCount_32f = 0.0f;
    IppStatus sum_status = ippsSum_32f(xor_result_32f, length, &errorCount_32f, ippAlgHintAccurate);

    if (sum_status != ippStsNoErr) {
        std::cout << "错误：IPP求和运算失败，错误代码：" << sum_status << std::endl;
        ippsFree(original_ipp);
        ippsFree(received_ipp);
        ippsFree(xor_result);
        ippsFree(xor_result_32f);
        return -1.0;
    }

    int errorCount = (int)(errorCount_32f + 0.5f); // 四舍五入转换为整数

    // 释放32f数组内存
    ippsFree(xor_result_32f);

    // 计算误码率
    float ber = (float)errorCount / (float)length;

    // 输出详细信息
    std::cout << "=== 误码率计算结果 ===" << std::endl;
    std::cout << "总比特数：" << length << std::endl;
    std::cout << "错误比特数：" << errorCount << std::endl;
    std::cout << "误码率（BER）：" << ber << std::endl;
    std::cout << "误码率（百分比）：" << ber * 100.0 << "%" << std::endl;

    // 释放内存
    ippsFree(original_ipp);
    ippsFree(received_ipp);
    ippsFree(xor_result);

    return ber;
}

void Cpl2Rev_SC(Ipp32fc* DataCpl, Ipp32s DataLen, Ipp32f* DataRev)
{
    // 遍历复数数组，只取实部存入实数数组
    for (Ipp32s i = 0; i < DataLen; i++) {
        DataRev[i] = DataCpl[i].re;  // 只取复数的实部
    }
}

void SynStep1_SC_Edited(Ipp32f* Syn_SigIn, Ipp32fc* BaseBandSig, Ipp32s Syn_SigLen, Ipp32fc* Syn_RefCopySam, Ipp32fc* Sig_blk, Ipp32fc* Syn_DataCache, Ipp32fc* Syn_DataCachePrmy, Ipp32s* Syn_PosFirst, Ipp8u* Syn_FlagFirst, Ipp32f g_Syn_Threshold, Ipp32s va_g_Syn_NFFT_RAW, Ipp32s va_g_Syn_BufSamCnt, Ipp32s va_g_Syn_BufCnt, Ipp32s va_g_SamStep)
{
    //同步标志位和同步坐标初始化
    Ipp32u Step = va_g_Syn_NFFT_RAW / 2;

    ///Section1 对得到的基带信号抽样
    Ipp32fc* BaseBandSigSam = ippsMalloc_32fc(va_g_Syn_BufSamCnt);
    ippsZero_32fc(BaseBandSigSam, va_g_Syn_BufSamCnt); // 初始化为零

    Ipp32u SamCnt = 0;
    for (SamCnt = 0; SamCnt < va_g_Syn_BufSamCnt; SamCnt++)
    {
        *(BaseBandSigSam + SamCnt) = *(BaseBandSig + SamCnt * va_g_SamStep);
    }

    ///Section2 频域实现拷贝相关器
    Ipp32fc* Syn_SigInfc = ippsMalloc_32fc(va_g_Syn_BufCnt);
    ippsZero_32fc(Syn_SigInfc, va_g_Syn_BufCnt); // 初始化为零

    //把Syn_DataCachePrmy第二个6144点信号移到前半部分，刚得到的6144点同步信号放入后半部分
    ippsMove_32fc(Syn_DataCachePrmy + va_g_Syn_BufCnt, Syn_DataCachePrmy, va_g_Syn_BufCnt);
    Rev2Cpl_SC(Syn_SigIn, va_g_Syn_BufCnt, Syn_SigInfc);
    ippsMove_32fc(Syn_SigInfc, Syn_DataCachePrmy + va_g_Syn_BufCnt, va_g_Syn_BufCnt);

    //把Syn_DataCache第二个6144点信号移到前半部分，刚得到的6144点同步信号放入后半部分
    ippsMove_32fc(Syn_DataCache + va_g_Syn_BufCnt, Syn_DataCache, va_g_Syn_BufCnt);
    ippsMove_32fc(BaseBandSig, Syn_DataCache + va_g_Syn_BufCnt, va_g_Syn_BufCnt);

    //把Sig_blk后半部分信号移到前半部分，刚抽样得到的1024点同步信号放入后半部分
    ippsMove_32fc(Sig_blk + Step, Sig_blk, Step);
    ippsMove_32fc(BaseBandSigSam, Sig_blk + Step, Step);

    //求向量总能量,归一化
    Ipp64fc Norm = { 0,0 };
    Ipp32fc Norm32 = { 0,0 };

    Ipp32fc* SigDownblk = ippsMalloc_32fc(va_g_Syn_NFFT_RAW);
    ippsZero_32fc(SigDownblk, va_g_Syn_NFFT_RAW); // 初始化为零

    Ipp32fc* SigDownblk_FD = ippsMalloc_32fc(va_g_Syn_NFFT_RAW);
    ippsZero_32fc(SigDownblk_FD, va_g_Syn_NFFT_RAW); // 初始化为零

    Ipp32fc* Syn_DotMul_FD = ippsMalloc_32fc(va_g_Syn_NFFT_RAW);
    ippsZero_32fc(Syn_DotMul_FD, va_g_Syn_NFFT_RAW); // 初始化为零

    Ipp32fc* CorrCur = ippsMalloc_32fc(va_g_Syn_NFFT_RAW);
    ippsZero_32fc(CorrCur, va_g_Syn_NFFT_RAW); // 初始化为零

    Ipp32f* CorrCurAbs = ippsMalloc_32f(va_g_Syn_NFFT_RAW);
    ippsZero_32f(CorrCurAbs, va_g_Syn_NFFT_RAW); // 初始化为零

    ippsNorm_L2_32fc64f(Sig_blk, va_g_Syn_NFFT_RAW, &(Norm.re));
    Norm32.re = (Ipp32f)Norm.re;
    ippsDivC_32fc(Sig_blk, Norm32, SigDownblk, va_g_Syn_NFFT_RAW);

    //FFT,点乘，IFFT
    Ipps_FFT_32fc_SC(SigDownblk, SigDownblk_FD, va_g_Syn_NFFT_RAW);
    ippsMul_32fc(SigDownblk_FD, Syn_RefCopySam, Syn_DotMul_FD, va_g_Syn_NFFT_RAW);
    Ipps_IFFT_32fc_SC(Syn_DotMul_FD, CorrCur, va_g_Syn_NFFT_RAW);

    //对相关结果取模
    ippsMagnitude_32fc(CorrCur, CorrCurAbs, va_g_Syn_NFFT_RAW);

    ///判断相关峰是否大于阈值
    Ipp32f MaxAbsCur = 0;
    Ipp32s MaxIndx = 0;
    ippsMaxAbsIndx_32f(CorrCurAbs, va_g_Syn_NFFT_RAW, &MaxAbsCur, &MaxIndx);

    if (MaxAbsCur > g_Syn_Threshold)
    {
        *Syn_FlagFirst = 1;
        *Syn_PosFirst = MaxIndx * va_g_SamStep + va_g_Syn_BufCnt;
    }
    else
    {
        *Syn_FlagFirst = 0;
        *Syn_PosFirst = -1;
    }

    //释放内存
    ippsFree(BaseBandSigSam);
    ippsFree(Syn_SigInfc);
    ippsFree(SigDownblk);
    ippsFree(SigDownblk_FD);
    ippsFree(Syn_DotMul_FD);
    ippsFree(CorrCur);
    ippsFree(CorrCurAbs);
}


// 接收信号归一化（默认无）+降采样+滤波
void DownConversion_MASS(Ipp32f* Syn_SigIn, Ipp32s Syn_SigLen, Ipp32fc* Syn_FIRCoe, Ipp32s Syn_FIRLen,
    Ipp32fc* BaseBandSig,Ipp32u va_g_f0,Ipp32u va_g_fs)
{
    //申请内存
    Ipp32u SigCnt = 0, FIRDelay = 0;
    Ipp32fc* MixSig = ippsMalloc_32fc(Syn_SigLen + Syn_FIRLen - 1);
    Ipp32fc* MixSigFIR = ippsMalloc_32fc(Syn_SigLen + Syn_FIRLen - 1);
    ippsZero_32fc(MixSig, Syn_SigLen + Syn_FIRLen - 1);
    ippsZero_32fc(MixSigFIR, Syn_SigLen + Syn_FIRLen - 1);
    ///Section1 乘负载波调制到基带
    //接收信号归一化
    Ipp32f Maxabs = 0;
    //ippsMaxAbs_32f(Syn_SigIn, g_Syn_BufCnt, &Maxabs);
    //ippsDivC_32f_I(Maxabs, Syn_SigIn, g_Syn_BufCnt);

    //生成负载波序列，一会儿放入初始化函数
    Ipp32f* VectorInt = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* SinVectorInt = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* CosVectorInt = ippsMalloc_32f(Syn_SigLen);


    Ipp32f* SigSin = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* SigCos = ippsMalloc_32f(Syn_SigLen);

    for (SigCnt = 0; SigCnt < Syn_SigLen; SigCnt++)
    {
        *(VectorInt + SigCnt) = (Ipp32f)(-2 * IPP_PI * va_g_f0 * SigCnt / va_g_fs);
    }
    //取Sin，点乘
    ippsSin_32f_A11(VectorInt, SinVectorInt, Syn_SigLen);
    ippsMul_32f(Syn_SigIn, SinVectorInt, SigSin, Syn_SigLen);
    //取Cos，点乘
    ippsCos_32f_A11(VectorInt, CosVectorInt, Syn_SigLen);
    ippsMul_32f(Syn_SigIn, CosVectorInt, SigCos, Syn_SigLen);
    //组合成复数
    ippsRealToCplx_32f(SigCos, SigSin, MixSig, Syn_SigLen);
    //把MixSig的后几位置零，为FIR滤波做准备
    ippsZero_32fc(MixSig + Syn_SigLen, Syn_FIRLen - 1);
    //低通滤波，通过导入的滤波器系数完成卷积
    MCSK_FIRSR(MixSig, Syn_SigLen + Syn_FIRLen - 1, Syn_FIRCoe, Syn_FIRLen, MixSigFIR);
    //截取滤波后的信号，去除时延
    FIRDelay = (Syn_FIRLen - 1) / 2;
    ippsCopy_32fc(MixSigFIR + FIRDelay, BaseBandSig, Syn_SigLen);

    //释放内存
    ippsFree(MixSig);
    ippsFree(MixSigFIR);
    ippsFree(VectorInt);
    ippsFree(SinVectorInt);
    ippsFree(CosVectorInt);
    ippsFree(SigSin);
    ippsFree(SigCos);

}



// FIR滤波
void MCSK_FIRSR(Ipp32fc* src, Ipp32s srclen, Ipp32fc* taps, Ipp32s tapslen, Ipp32fc* dst)
{
    IppsFIRSpec_32fc* pSpec;
    Ipp8u* buf;
    int             specSize, bufSize;
    IppStatus status;
    //get sizes of the spec structure and the work buffer
    status = ippsFIRSRGetSize(tapslen, ipp32fc, &specSize, &bufSize);


    Ipp32fc* dly = ippsMalloc_32fc(tapslen - 1);

    pSpec = (IppsFIRSpec_32fc*)ippsMalloc_8u(specSize);
    buf = ippsMalloc_8u(bufSize);

    //initialize the spec structure
    ippsFIRSRInit_32fc(taps, tapslen, ippAlgAuto, pSpec);
    //apply the FIR filter
    ippsFIRSR_32fc(src, dst, srclen, pSpec, NULL, dly, buf);
    //释放内存
    ippsFree(dly);
    ippsFree(pSpec);
    ippsFree(buf);
}
//Mass解码函数
void MassDecode(Ipp32fc* Mass_SigRec, Ipp8u* Mass_BitsDecoded, Ipp32u va_g_f0, Ipp32u va_g_fs)
{
    //Mass解码
    //Step1 取同步完的信号的实部作为输入
    Ipp32f* Syn_SigRec_real = ippsMalloc_32f(MA_g_InfoSamPointTotalSyn);
    Ipp32f* Syn_SigRec_imag = ippsMalloc_32f(MA_g_InfoSamPointTotalSyn);

    ippsCplxToReal_32fc(Mass_SigRec, Syn_SigRec_real, Syn_SigRec_imag, MA_g_InfoSamPointTotalSyn);

    //Step2 解调到基带
    Ipp32fc* Mass_BaseBandSig = ippsMalloc_32fc(MA_g_InfoSamPointTotalSyn);

    DownConversion_MASS(Syn_SigRec_real, MA_g_InfoSamPointTotalSyn, Mass_FIRCoe, Mass_FIRCoe_len, Mass_BaseBandSig, va_g_f0, va_g_fs);

    //Step3 降采样
    Ipp32s  SigDownLen = MA_g_InfoSamPointTotalSyn / g_UpSamplingMultiple_Mass;
    Ipp32fc* SigDownResmale = ippsMalloc_32fc(SigDownLen);
    for (Ipp32s i = 0; i < SigDownLen; i++)
    {
        SigDownResmale[i].re = Mass_BaseBandSig[i * g_UpSamplingMultiple_Mass].re;
        SigDownResmale[i].im = Mass_BaseBandSig[i * g_UpSamplingMultiple_Mass].im;
        //ippsSum_32fc(Mass_BaseBandSig + i * g_UpSamplingMultiple_Mass, g_UpSamplingMultiple_Mass, SigDownResmale + i, ippAlgHintAccurate);
    }

    //Step4 数据解码
    Ipp32s* pos = ippsMalloc_32s(g_InfoSymbolNumPerFrame_Mass);
    Ipp32s* PosMary = ippsMalloc_32s(g_InfoSymbolNumPerFrame_Mass);
    Ipp32s* peak_out = ippsMalloc_32s(g_InfoSymbolNumPerFrame_Mass);

    //将这些值置零
    ippsZero_32s(pos, g_InfoSymbolNumPerFrame_Mass);
    ippsZero_32s(PosMary, g_InfoSymbolNumPerFrame_Mass);
    ippsZero_32s(peak_out, g_InfoSymbolNumPerFrame_Mass);

    //开始解码
    Ipp32s PoiltSigLen = g_PolitSymbolUsed_Mass * g_SpreadCodeLen_Mass;
    Ipp32s AddPoiltSigLen = PoiltSigLen + g_SpreadCodeLen_Mass;

    // 创建PolitSig的局部副本，避免修改全局变量
    Ipp32fc* PolitSig_local = ippsMalloc_32fc(PoiltSigLen);
    ippsCopy_32fc(PolitSig, PolitSig_local, PoiltSigLen);

    Ipp32fc* sig_temp = ippsMalloc_32fc((g_PolitSymbolUsed_Mass + 1) * g_SpreadCodeLen_Mass);
    Ipp32fc* DeSpreadCodeAddPolit = ippsMalloc_32fc(g_M_Mass * AddPoiltSigLen);
    Ipp32fc* DeSpreadCodeMatrix = ippsMalloc_32fc((2 * g_SlidingInterval_Mass + 1) * g_M_Mass * AddPoiltSigLen);
    Ipp32fc* y = ippsMalloc_32fc((2 * g_SlidingInterval_Mass + 1) * g_M_Mass);
    Ipp32f* sig_y = ippsMalloc_32f((2 * g_SlidingInterval_Mass + 1) * g_M_Mass);

    ippsZero_32fc(sig_temp, (g_PolitSymbolUsed_Mass + 1) * g_SpreadCodeLen_Mass);
    ippsZero_32fc(DeSpreadCodeAddPolit, g_M_Mass * AddPoiltSigLen);
    ippsZero_32fc(DeSpreadCodeMatrix, (2 * g_SlidingInterval_Mass + 1) * g_M_Mass * AddPoiltSigLen);
    ippsZero_32fc(y, (2 * g_SlidingInterval_Mass + 1) * g_M_Mass);
    ippsZero_32f(sig_y, (2 * g_SlidingInterval_Mass + 1) * g_M_Mass);

    for (Ipp32s ii = g_PolitSymbolNumPerFrame_Mass; ii < g_TotalSymbolNumPerFrame_Mass; ii++)
    {
        //取出当前解码序列
        ippsCopy_32fc(SigDownResmale + (ii - g_PolitSymbolUsed_Mass) * g_SpreadCodeLen_Mass, sig_temp, (g_PolitSymbolUsed_Mass + 1) * g_SpreadCodeLen_Mass);
        //构造一个包含导频和本地扩频序列的大矩阵
        for (Ipp32s jj = 0; jj < g_M_Mass; jj++)
        {
            ippsCopy_32fc(PolitSig_local, DeSpreadCodeAddPolit + jj * AddPoiltSigLen, PoiltSigLen);
            ippsCopy_32fc(DeSpreadCode[jj], DeSpreadCodeAddPolit + jj * AddPoiltSigLen + PoiltSigLen, g_SpreadCodeLen_Mass);
        }

        //把用导频扩展后的扩频矩阵生成解码需要的矩阵
        Ipp32s rr = 1;
        for (Ipp32s t = g_SlidingInterval_Mass; t > 0; t--)
        {
            for (Ipp32s jj = 0; jj < g_M_Mass; jj++)
            {
                ippsCopy_32fc(DeSpreadCodeAddPolit + jj * AddPoiltSigLen + (AddPoiltSigLen - t), DeSpreadCodeMatrix + jj * AddPoiltSigLen + (rr - 1) * g_M_Mass * AddPoiltSigLen, t);
                ippsCopy_32fc(DeSpreadCodeAddPolit + jj * AddPoiltSigLen, DeSpreadCodeMatrix + jj * AddPoiltSigLen + t + (rr - 1) * g_M_Mass * AddPoiltSigLen, AddPoiltSigLen - t);
            }
            rr = rr + 1;
        }

        for (Ipp32s t = 1; t <= g_SlidingInterval_Mass + 1; t++)
        {
            for (Ipp32s jj = 0; jj < g_M_Mass; jj++)
            {
                ippsCopy_32fc(DeSpreadCodeAddPolit + jj * AddPoiltSigLen + (t - 1), DeSpreadCodeMatrix + jj * AddPoiltSigLen + (t - 1) * g_M_Mass * AddPoiltSigLen + g_SlidingInterval_Mass * g_M_Mass * AddPoiltSigLen, AddPoiltSigLen - (t - 1));
                ippsCopy_32fc(DeSpreadCodeAddPolit + jj * AddPoiltSigLen, DeSpreadCodeMatrix + jj * AddPoiltSigLen + (AddPoiltSigLen - (t - 1)) + (t - 1) * g_M_Mass * AddPoiltSigLen + g_SlidingInterval_Mass * g_M_Mass * AddPoiltSigLen, t - 1);
            }
        }

        //向量与矩阵转置的乘法，即向量与未转置的矩阵的共轭每一行做点乘累加
        //因为是扩频码没有虚部，不做共轭，直接循环每一行
        for (Ipp32s jj = 0; jj < (2 * g_SlidingInterval_Mass + 1) * g_M_Mass; jj++)
        {
            ippsDotProd_32fc(sig_temp, DeSpreadCodeMatrix + jj * AddPoiltSigLen, AddPoiltSigLen, y + jj);
        }
        //求能量
        ippsPowerSpectr_32fc(y, sig_y, (2 * g_SlidingInterval_Mass + 1) * g_M_Mass);
        //找出能量最大的位置
        Ipp32f MaxValue = 0;
        ippsMaxIndx_32f(sig_y, (2 * g_SlidingInterval_Mass + 1) * g_M_Mass, &MaxValue, pos + ii - g_PolitSymbolNumPerFrame_Mass);
        //找出是哪个扩频序列
        *(PosMary + ii - g_PolitSymbolNumPerFrame_Mass) = (*(pos + ii - g_PolitSymbolNumPerFrame_Mass)) % g_M_Mass;
        //更新导频信号（使用局部副本）
        ippsCopy_32fc(PolitSig_local + g_SpreadCodeLen_Mass, PolitSig_local, PoiltSigLen - g_SpreadCodeLen_Mass);
        ippsCopy_32fc(DeSpreadCode[*(PosMary + ii - g_PolitSymbolNumPerFrame_Mass)], PolitSig_local + PoiltSigLen - g_SpreadCodeLen_Mass, g_SpreadCodeLen_Mass);
        //得到输出
        *(peak_out + ii - g_PolitSymbolNumPerFrame_Mass) = *(PosMary + ii - g_PolitSymbolNumPerFrame_Mass);
        if (*(peak_out + ii - g_PolitSymbolNumPerFrame_Mass) == g_M_Mass)
        {
            *(peak_out + ii - g_PolitSymbolNumPerFrame_Mass) = 0;
        }
    }

    //Step5 十进制转化为二进制char
    for (Ipp32s Sym = 0; Sym < g_InfoSymbolNumPerFrame_Mass; Sym++)
    {
        for (Ipp32s Mcnt = 0; Mcnt < g_r_Mass; Mcnt++)
        {
            Mass_BitsDecoded[g_r_Mass * Sym + Mcnt] = *(peak_out + Sym) & 1;

            *(peak_out + Sym) >>= 1;
        }
        ippsFlip_8u_I(Mass_BitsDecoded + g_r_Mass * Sym, g_r_Mass);
    }
    for (Ipp32s Sym = 0; Sym < g_InfoBitNumTotalPerFrame_Mass; Sym++)
    {
        if (Mass_BitsDecoded[Sym] == 1)
            Mass_BitsDecoded[Sym] = '1';
        else
            Mass_BitsDecoded[Sym] = '0';
    }

    //释放内存
    ippsFree(PolitSig_local);  // 新增：释放局部PolitSig副本
    ippsFree(Syn_SigRec_real);
    ippsFree(Syn_SigRec_imag);
    ippsFree(Mass_BaseBandSig);
    ippsFree(SigDownResmale);
    ippsFree(pos);
    ippsFree(PosMary);
    ippsFree(peak_out);
    ippsFree(sig_temp);
    ippsFree(DeSpreadCodeAddPolit);
    ippsFree(DeSpreadCodeMatrix);
    ippsFree(y);
    ippsFree(sig_y);
}

void GenerateQPSKSignal(
    // 输入参数 - 常量部分
    Ipp32f fs,                    // 采样频率
    Ipp32f f0_1,                  // 载波频率
    Ipp32f R_s1,                  // 有效符号速率
    Ipp32f alpha_1,               // 滚降系数
    Ipp32s M,                     // 调制阶数
    Ipp32s bitnum_per,            // 每符号比特数
    Ipp32f Sym_time,              // 有效符号持续时间
    Ipp32s Numburst,              // 突发数量
    Ipp32s Numblock_perburst,     // 每突发块数

    // 输入参数 - 线性调频信号
    Ipp32f* sig_syn_LFM_1,        // 线性调频信号
    Ipp32s syn_length,            // 线性调频信号长度

    // 输入参数 - 数据
    Ipp8u* data,                 // 输入数据
    Ipp32s data_length,           // 数据长度

    Ipp32f* p_1,                 // 根升余弦滤波器系数
    Ipp32s p_1_length,            // 根升余弦滤波器长度

    // 输出参数
    Ipp32f* signal_send_1,        // 输出信号
    int* output_length         // 输出信号长度
)
{
    // 计算内部变量
    Ipp32s N_pn_1 = (Ipp32s)floor(fs / R_s1);  // 升采样点数
    Ipp32s delay_length = (Ipp32s)(0.5 * fs);   // 延迟长度
    Ipp32s Numsym_perblock = (Ipp32s)(Sym_time * R_s1); // 每块符号数

    // 对输入的线性调频信号乘以系数
    Ipp32f* scaled_LFM = ippsMalloc_32f(syn_length);
    ippsMulC_32f(sig_syn_LFM_1, 0.7f, scaled_LFM, syn_length);

    // 生成延迟（零序列）
    Ipp32f* delay = ippsMalloc_32f(delay_length);
    ippsZero_32f(delay, delay_length);

    // 开始处理每个突发
    for (Ipp32s ii = 0; ii < Numburst; ii++) {
        // PSK调制 - 使用查找表方式实现QPSK
        Ipp32s total_symbols = data_length / 2;
        Ipp32fc* sympol_1_with_train_seq = ippsMalloc_32fc(total_symbols + train_sequence_len);
        ippsZero_32fc(sympol_1_with_train_seq, total_symbols + train_sequence_len);
        //// QPSK星座点 (pi/4相移)
        //Ipp32fc qpsk_table[4] = {
        //    {cos(IPP_PI / 4), sin(IPP_PI / 4)},       // 00
        //    {cos(3 * IPP_PI / 4), sin(3 * IPP_PI / 4)},   // 01  
        //    {cos(-IPP_PI / 4), sin(-IPP_PI / 4)},      // 10
        //    {cos(-3 * IPP_PI / 4), sin(-3 * IPP_PI / 4)} // 11

        //};
        //// 进行QPSK调制
        //for (Ipp32s j = 0; j < total_symbols; j++) {
        //    Ipp32s symbol_index = data[total_symbols * ii + j] % 4;
        //    sympol_1_with_train_seq[j + train_sequence_len] = qpsk_table[symbol_index];
        //}
        Mapping(data, data_length, 4, sympol_1_with_train_seq + train_sequence_len, Table);



        ippsCopy_32fc(train_sequence, sympol_1_with_train_seq, train_sequence_len);

        // 分离I路和Q路
        Ipp32f* sympol_real_1 = ippsMalloc_32f(total_symbols + train_sequence_len);
        Ipp32f* sympol_imag_1 = ippsMalloc_32f(total_symbols + train_sequence_len);

        ippsReal_32fc(sympol_1_with_train_seq, sympol_real_1, total_symbols + train_sequence_len);
        ippsImag_32fc(sympol_1_with_train_seq, sympol_imag_1, total_symbols + train_sequence_len);

        // I路和Q路插值（升采样）
        Ipp32s upsampled_length = N_pn_1 * (total_symbols + train_sequence_len);
        Ipp32f* pams_I_1 = ippsMalloc_32f(upsampled_length);
        Ipp32f* pams_Q_1 = ippsMalloc_32f(upsampled_length);

        ippsZero_32f(pams_I_1, upsampled_length);
        ippsZero_32f(pams_Q_1, upsampled_length);

        // 插值 - 每N_pn_1个点插入一个符号
        for (Ipp32s j = 0; j < total_symbols + train_sequence_len; j++) {
            pams_I_1[j * N_pn_1] = sympol_real_1[j];
            pams_Q_1[j * N_pn_1] = sympol_imag_1[j];
        }

        // 添加零填充用于滤波
        Ipp32s padded_length = upsampled_length + p_1_length / 2;
        Ipp32f* pams_I_padded = ippsMalloc_32f(padded_length);
        Ipp32f* pams_Q_padded = ippsMalloc_32f(padded_length);

        ippsCopy_32f(pams_I_1, pams_I_padded, upsampled_length);
        ippsZero_32f(pams_I_padded + upsampled_length, p_1_length / 2);
        ippsCopy_32f(pams_Q_1, pams_Q_padded, upsampled_length);
        ippsZero_32f(pams_Q_padded + upsampled_length, p_1_length / 2);

        // 整形滤波（根升余弦滤波）
        Ipp32f* ynI_1_temp = ippsMalloc_32f(padded_length);
        Ipp32f* ynQ_1_temp = ippsMalloc_32f(padded_length);


        // FIR滤波
        SC_FIR_Real(pams_I_padded, padded_length, p_1, p_1_length, ynI_1_temp);
        SC_FIR_Real(pams_Q_padded, padded_length, p_1, p_1_length, ynQ_1_temp);

        // 去除滤波延迟
        Ipp32s filtered_length = upsampled_length;
        Ipp32f* ynI_1 = ippsMalloc_32f(filtered_length);
        Ipp32f* ynQ_1 = ippsMalloc_32f(filtered_length);

        Ipp32s delay_samples = p_1_length / 2;
        ippsCopy_32f(ynI_1_temp + delay_samples, ynI_1, filtered_length);
        ippsCopy_32f(ynQ_1_temp + delay_samples, ynQ_1, filtered_length);

        // 载波调制
        Ipp32f* t = ippsMalloc_32f(filtered_length);
        Ipp32f* y_cos_1 = ippsMalloc_32f(filtered_length);
        Ipp32f* y_sin_1 = ippsMalloc_32f(filtered_length);

        // 生成时间向量
        for (Ipp32s j = 0; j < filtered_length; j++) {
            t[j] = (Ipp32f)j / fs;
        }

        // 生成载波
        Ipp32f* temp_cos = ippsMalloc_32f(filtered_length);
        Ipp32f* temp_sin = ippsMalloc_32f(filtered_length);

        ippsMulC_32f(t, 2 * IPP_PI * f0_1, temp_cos, filtered_length);
        ippsCopy_32f(temp_cos, temp_sin, filtered_length);

        ippsCos_32f_A11(temp_cos, y_cos_1, filtered_length);
        ippsSin_32f_A11(temp_sin, y_sin_1, filtered_length);

        // QPSK调制: I*cos + Q*sin
        Ipp32f* sig_qpsk1_1 = ippsMalloc_32f(filtered_length);
        Ipp32f* temp_I = ippsMalloc_32f(filtered_length);
        Ipp32f* temp_Q = ippsMalloc_32f(filtered_length);

        ippsMul_32f(ynI_1, y_cos_1, temp_I, filtered_length);
        ippsMul_32f(ynQ_1, y_sin_1, temp_Q, filtered_length);
        ippsAdd_32f(temp_I, temp_Q, sig_qpsk1_1, filtered_length);

        // 归一化
        Ipp32f max_val;
        ippsMaxAbs_32f(sig_qpsk1_1, filtered_length, &max_val);
        if (max_val > 0) {
            ippsDivC_32f_I(max_val, sig_qpsk1_1, filtered_length);
        }

        // 组合最终信号: [LFM + delay + QPSK + delay + LFM]
        Ipp32s sig_qpsk_length = syn_length + delay_length + filtered_length + delay_length + syn_length;
        Ipp32f* sig_qpsk_1 = ippsMalloc_32f(sig_qpsk_length);

        Ipp32s offset = 0;
        ippsCopy_32f(scaled_LFM, sig_qpsk_1 + offset, syn_length);
        offset += syn_length;

        ippsCopy_32f(delay, sig_qpsk_1 + offset, delay_length);
        offset += delay_length;

        ippsCopy_32f(sig_qpsk1_1, sig_qpsk_1 + offset, filtered_length);
        offset += filtered_length;

        ippsCopy_32f(delay, sig_qpsk_1 + offset, delay_length);
        offset += delay_length;

        ippsCopy_32f(scaled_LFM, sig_qpsk_1 + offset, syn_length);

        // 最终输出信号: [delay + sig_qpsk_1]
        *output_length = delay_length + sig_qpsk_length;
        ippsCopy_32f(delay, signal_send_1, delay_length);
        ippsCopy_32f(sig_qpsk_1, signal_send_1 + delay_length, sig_qpsk_length);
        // 释放内存
        ippsFree(sympol_1_with_train_seq);
        ippsFree(sympol_real_1);
        ippsFree(sympol_imag_1);
        ippsFree(pams_I_1);
        ippsFree(pams_Q_1);
        ippsFree(pams_I_padded);
        ippsFree(pams_Q_padded);
        ippsFree(ynI_1_temp);
        ippsFree(ynQ_1_temp);
        ippsFree(ynI_1);
        ippsFree(ynQ_1);

        ippsFree(t);
        ippsFree(y_cos_1);
        ippsFree(y_sin_1);
        ippsFree(temp_cos);
        ippsFree(temp_sin);
        ippsFree(sig_qpsk1_1);
        ippsFree(temp_I);
        ippsFree(temp_Q);
        ippsFree(sig_qpsk_1);
    }

    // 释放内存
    ippsFree(scaled_LFM);
    ippsFree(delay);
}

// 辅助函数：实数FIR滤波（同之前的定义）
void SC_FIR_Real(Ipp32f* src, Ipp32s srclen, Ipp32f* taps, Ipp32s tapslen, Ipp32f* dst)
{
    IppsFIRSpec_32f* pSpec;
    Ipp8u* buf;
    int specSize, bufSize;
    IppStatus status;

    // 获取规格结构和工作缓冲区的大小
    status = ippsFIRSRGetSize(tapslen, ipp32f, &specSize, &bufSize);

    Ipp32f* dly = ippsMalloc_32f(tapslen - 1);
    pSpec = (IppsFIRSpec_32f*)ippsMalloc_8u(specSize);
    buf = ippsMalloc_8u(bufSize);

    // 初始化规格结构
    ippsFIRSRInit_32f(taps, tapslen, ippAlgAuto, pSpec);

    // 应用FIR滤波器
    ippsFIRSR_32f(src, dst, srclen, pSpec, NULL, dly, buf);

    // 释放内存
    ippsFree(dly);
    ippsFree(pSpec);
    ippsFree(buf);
}





int* function_loadbw(const char* filename, int N, int& data_size) {
    // 1. 读取图像 (OpenCV默认是BGR格式)
    cv::Mat img = cv::imread(filename, cv::IMREAD_COLOR);
    if (img.empty()) {
        std::cerr << "错误:无法加载图像 " << filename << std::endl;
        data_size = 0;
        return nullptr;
    }

    // 2. 调整图像尺寸 (与MATLAB的imresize对应)
    cv::Mat resized;
    cv::resize(img, resized, cv::Size(N, N));

    // 3. 转换为灰度图像 (模拟MATLAB的rgb2gray)
    cv::Mat gray;
    if (resized.channels() == 3) {
        // 注意:OpenCV是BGR,MATLAB是RGB,但rgb2gray的权重是一样的
        cv::cvtColor(resized, gray, cv::COLOR_BGR2GRAY);
    }
    else {
        gray = resized.clone();
    }

    // 4. 转换为double类型并归一化到[0,1] (模拟MATLAB的数据类型)
    cv::Mat gray_double;
    gray.convertTo(gray_double, CV_64F, 1.0 / 255.0);

    // 5. 二值化 (模拟MATLAB的imbinarize(Gray, 0.7))
    cv::Mat BW;
    cv::threshold(gray_double, BW, 0.7, 1.0, cv::THRESH_BINARY);

    // 6. 显示图像 (对应MATLAB的imshow)
    cv::Mat display_img;
    //BW.convertTo(display_img, CV_8U, 255); // 转换为0-255用于显示
    //cv::namedWindow("发送图片", cv::WINDOW_AUTOSIZE);
    //cv::imshow("发送图片", display_img);
    //cv::waitKey(1); // 非阻塞显示

    // 7. 计算数据大小
    data_size = BW.rows * BW.cols;

    // 8. 分配内存用于输出 (现在使用int类型)
    int* img_data = new int[data_size];

    // 9. **关键**:按列优先顺序复制数据 (模拟MATLAB的reshape(BW, 1, []))
    // MATLAB是列优先存储,OpenCV是行优先存储
    // 将double值转换为int (0.0->0, 1.0->1)
    for (int col = 0; col < BW.cols; ++col) {
        for (int row = 0; row < BW.rows; ++row) {
            int matlab_index = col * BW.rows + row;  // 列优先索引

            // 添加边界检查以防止缓冲区溢出
            if (matlab_index >= 0 && matlab_index < data_size) {
                img_data[matlab_index] = static_cast<int>(BW.at<double>(row, col));
            }
            else {
                std::cerr << "错误: 数组索引越界 " << matlab_index << " >= " << data_size << std::endl;
                delete[] img_data;
                data_size = 0;
                return nullptr;
            }
        }
    }
    return img_data;
}


bool function_savebw(const char* img_data, int N, int data_size, const char* output_filename) {
    // 1. 检查输入参数
    if (img_data == nullptr || data_size <= 0 || N <= 0 || output_filename == nullptr) {
        std::cerr << "错误：无效的输入参数" << std::endl;
        return false;
    }

    // 2. 验证数据大小
    if (data_size != N * N) {
        std::cerr << "错误：数据大小不匹配，期望 " << N * N << "，实际 " << data_size << std::endl;
        return false;
    }

    // 3. 创建OpenCV Mat对象
    cv::Mat save_img(N, N, CV_8U);

    // 4. **关键修正**：按列优先顺序读取数据，按行优先顺序填充OpenCV Mat
    // 这是function_loadbw的逆操作
    for (int col = 0; col < N; ++col) {
        for (int row = 0; row < N; ++row) {
            int matlab_index = col * N + row;  // 列优先索引（与loadbw一致）

            // 边界检查
            if (matlab_index >= 0 && matlab_index < data_size) {
                // 假设char数据是'0'/'1'字符，转换为0/255用于保存
                if (img_data[matlab_index] == '1') {
                    save_img.at<uint8_t>(row, col) = 255;
                }
                else if (img_data[matlab_index] == '0') {
                    save_img.at<uint8_t>(row, col) = 0;
                }
                else {
                    // 处理非预期字符
                    std::cerr << "警告：位置 " << matlab_index << " 处发现非预期字符 '"
                        << img_data[matlab_index] << "'" << std::endl;
                    save_img.at<uint8_t>(row, col) = 0; // 默认设为0
                }
            }
            else {
                std::cerr << "错误: 数组索引越界 " << matlab_index << " >= " << data_size << std::endl;
                return false;
            }
        }
    }

    // 5. 保存图像到本地
    bool success = cv::imwrite(output_filename, save_img);
    if (success) {
        std::cout << "图像已成功保存到: " << output_filename << std::endl;
    }
    else {
        std::cerr << "错误：无法保存图像到 " << output_filename << std::endl;
    }

    return success;
}





void GenerateQPSKSignal_Wrapper(
    // 输入参数 - 常量部分
    Ipp32f fs,                    // 采样频率
    Ipp32f f0_1,                  // 载波频率
    Ipp32f f0_2,                  // 载波频率
    Ipp32f R_s1,                  // 有效符号速率
    Ipp32f alpha_1,               // 滚降系数
    Ipp32s M,                     // 调制阶数
    Ipp32s bitnum_per,            // 每符号比特数
    Ipp32f Sym_time,              // 有效符号持续时间
    Ipp32s Numburst,              // 突发数量
    Ipp32s Numblock_perburst,     // 每突发块数

    // 输入参数 - 线性调频信号
    Ipp32f* sig_syn_LFM_1,        // 线性调频信号
    Ipp32f* sig_syn_LFM_2,        // 线性调频信号
    Ipp32s syn_length,            // 线性调频信号长度

    Ipp32f* p_1,                 // 根升余弦滤波器系数
    Ipp32s p_1_length,            // 根升余弦滤波器长度

    
    
    const char* filename, int N, int& data_size,Ipp32f* signal_send_1, Ipp32f* signal_send_2, int* output_length)
{

    int* result = function_loadbw(filename, N, data_size);

    char* char_data = new char[MQPSK_N * MQPSK_N + 1]; // +1为字符串结束符

    for (int i = 0; i < MQPSK_N * MQPSK_N; i++) {
        if (result[i] == 1) {
            char_data[i] = '1';
        }
        else {
            char_data[i] = '0';
        }
    }
    char_data[MQPSK_N * MQPSK_N] = '\0'; // 字符串结束符


    //bool IS_SAVED = function_savebw(char_data, MQPSK_N, data_size, "GEN_img.png");


    Ipp8u* data_1 = ippsMalloc_8u(MQPSK_data_length);
    ippsZero_8u(data_1, MQPSK_data_length);
    for (int i = 0; i < (MQPSK_N * MQPSK_N) / 2; i++) {
        data_1[i] = static_cast<Ipp8u>(result[i]);
    }

    Ipp8u* data_2 = ippsMalloc_8u(MQPSK_data_length);
    ippsZero_8u(data_2, MQPSK_data_length);
    for (int i = 0; i < (MQPSK_N * MQPSK_N) / 2; i++) {
        data_2[i] = static_cast<Ipp8u>(result[(MQPSK_N * MQPSK_N) / 2 + i]);
    }

    //Load8uData("IPPS_data.txt",data_1, MQPSK_data_length);
    //Load8uData("IPPS_data_2.txt", data_2, MQPSK_data_length);



    GenerateQPSKSignal(
        // 输入参数 - 常量部分
        fs,                    // 采样频率
        f0_1,                  // 载波频率
        R_s1,                  // 有效符号速率
        alpha_1,               // 滚降系数
        M,                     // 调制阶数
        bitnum_per,            // 每符号比特数
        Sym_time,              // 有效符号持续时间
        Numburst,              // 突发数量
        Numblock_perburst,     // 每突发块数

        // 输入参数 - 线性调频信号
        sig_syn_LFM_1,        // 线性调频信号
        syn_length,            // 线性调频信号长度

        // 输入参数 - 数据
        data_1,                 // 输入数据
        MQPSK_data_length,           // 数据长度

        // 预计算的滤波器系数
        p_1,                 // 根升余弦滤波器系数
        p_1_length,            // 根升余弦滤波器长度

        // 输出参数
        signal_send_1,        // 输出信号
        output_length         // 输出信号长度

    );
    GenerateQPSKSignal(
        // 输入参数 - 常量部分
        fs,                    // 采样频率
        f0_2,                  // 载波频率
        R_s1,                  // 有效符号速率
        alpha_1,               // 滚降系数
        M,                     // 调制阶数
        bitnum_per,            // 每符号比特数
        Sym_time,              // 有效符号持续时间
        Numburst,              // 突发数量
        Numblock_perburst,     // 每突发块数

        // 输入参数 - 线性调频信号
        sig_syn_LFM_2,        // 线性调频信号
        syn_length,            // 线性调频信号长度

        // 输入参数 - 数据
        data_2,                 // 输入数据
        MQPSK_data_length,           // 数据长度

        // 预计算的滤波器系数
        p_1,                 // 根升余弦滤波器系数
        p_1_length,            // 根升余弦滤波器长度

        // 输出参数
        signal_send_2,        // 输出信号
        output_length         // 输出信号长度

    );



}
//时域，解调+滤波+降采样
void DownConversion_QPSK(Ipp32f* Syn_SigIn, Ipp32s Syn_SigLen, Ipp32fc* Syn_FIRCoe, Ipp32s Syn_FIRLen,
    Ipp32fc* BaseBandSig, Ipp32u va_g_f0, Ipp32u va_g_fs, Ipp32u va_N_upsample)
{
    //申请内存
    Ipp32u SigCnt = 0, FIRDelay = 0;
    Ipp32fc* MixSig = ippsMalloc_32fc(Syn_SigLen + Syn_FIRLen - 1);
    Ipp32fc* MixSigFIR = ippsMalloc_32fc(Syn_SigLen + Syn_FIRLen - 1);
    ippsZero_32fc(MixSig, Syn_SigLen + Syn_FIRLen - 1);
    ippsZero_32fc(MixSigFIR, Syn_SigLen + Syn_FIRLen - 1);
    ///Section1 乘负载波调制到基带
    //接收信号归一化
    Ipp32f Maxabs = 0;
    //ippsMaxAbs_32f(Syn_SigIn, g_Syn_BufCnt, &Maxabs);
    //ippsDivC_32f_I(Maxabs, Syn_SigIn, g_Syn_BufCnt);

    //生成负载波序列，一会儿放入初始化函数
    Ipp32f* VectorInt = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* SinVectorInt = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* CosVectorInt = ippsMalloc_32f(Syn_SigLen);


    Ipp32f* SigSin = ippsMalloc_32f(Syn_SigLen);
    Ipp32f* SigCos = ippsMalloc_32f(Syn_SigLen);

    for (SigCnt = 0; SigCnt < Syn_SigLen; SigCnt++)
    {
        *(VectorInt + SigCnt) = (Ipp32f)(-2 * IPP_PI * va_g_f0 * SigCnt / va_g_fs);
    }
    //取Sin，点乘
    ippsSin_32f_A11(VectorInt, SinVectorInt, Syn_SigLen);
    ippsMul_32f(Syn_SigIn, SinVectorInt, SigSin, Syn_SigLen);
    //取Cos，点乘
    ippsCos_32f_A11(VectorInt, CosVectorInt, Syn_SigLen);
    ippsMul_32f(Syn_SigIn, CosVectorInt, SigCos, Syn_SigLen);
    //组合成复数
    ippsRealToCplx_32f(SigCos, SigSin, MixSig, Syn_SigLen);
    //把MixSig的后几位置零，为FIR滤波做准备
    ippsZero_32fc(MixSig + Syn_SigLen, Syn_FIRLen - 1);




    for (int i = 0; i < Syn_SigLen + Syn_FIRLen - 1; i++)
    {
        MixSig[i].im = -MixSig[i].im;
    }
    Ipp32fc* filteredSignal = (Ipp32fc*)ippsMalloc_32fc(Syn_SigLen + Syn_FIRLen); // 分配内存用于存储滤波结果


    SC_FIR(MixSig, Syn_SigLen + ((Syn_FIRLen - 1) / 2), Syn_FIRCoe, Syn_FIRLen, filteredSignal); // FIR 滤波，这个测试了没问题

    Ipp32fc* OutputSignal = (Ipp32fc*)ippsMalloc_32fc(Syn_SigLen);   // 分配内存用于最终输出

    FIRDelay = (Syn_FIRLen - 1) / 2; // 等效于 fix(length(PulseShape)/2)
    ippsCopy_32fc(filteredSignal + FIRDelay, OutputSignal, Syn_SigLen); // 裁剪延迟

    /// Section 2: 实现降采样
    Ipp32s LengthOutSignal = Syn_SigLen;      // 滤波后的信号长度
    Ipp32s LengthAftDown = LengthOutSignal / va_N_upsample; // 降采样后的信号长度
    Ipp32fc* TempDownSampledSig = ippsMalloc_32fc(LengthAftDown);

    for (Ipp32s i = 0; i < LengthAftDown && i * va_N_upsample < LengthOutSignal; i++) {
        TempDownSampledSig[i].re = 2 * OutputSignal[i * va_N_upsample].re; // 实部乘以 2
        TempDownSampledSig[i].im = 2 * OutputSignal[i * va_N_upsample].im; // 虚部乘以 2
    }
    ippsCopy_32fc(TempDownSampledSig, BaseBandSig, LengthAftDown);
    //释放内存
    ippsFree(MixSig);
    ippsFree(MixSigFIR);
    ippsFree(VectorInt);
    ippsFree(SinVectorInt);
    ippsFree(CosVectorInt);
    ippsFree(SigSin);
    ippsFree(SigCos);
    ippsFree(TempDownSampledSig);

}

float Calculate_BER_AND_SAVE_IMG(Ipp8u* BitsAftDemaapping_1, Ipp8u* BitsAftDemaapping_2,
    const char* file_name, Ipp8u va_MQPSK_N, Ipp8u va_MQPSK_data_length) {

    OutputDebugString(L"真的太狠了，竟然进来了这个最终的计算误码率生成图片的函数里面了aaaaaaaaaaaa");
    int target_length = (va_MQPSK_N * va_MQPSK_N) / 2;

    // 直接创建目标大小的字符串，避免多次内存重分配
    std::string merged_bits;
    merged_bits.reserve(target_length * 2 + 1); // +1 为null终止符预留空间

    // 直接构建合并后的位串，避免中间字符串
    for (int i = 0; i < target_length; i++) {
        merged_bits += (BitsAftDemaapping_1[i] == 0 ? '0' : '1');
    }
    for (int i = 0; i < target_length; i++) {
        merged_bits += (BitsAftDemaapping_2[i] == 0 ? '0' : '1');
    }

    int data_size = 0;
    int* originalBits = function_loadbw(file_name, va_MQPSK_N, data_size);

    std::unique_ptr<char[]> originalBits_char(new char[MQPSK_N * MQPSK_N]);

    for (int i = 0; i < (MQPSK_N * MQPSK_N); i++) {
        originalBits_char[i] = static_cast<char>(originalBits[i]);
    }

    //SaveCharData("IPPS_merged_bits.txt", merged_bits.c_str(), target_length * 2);
    bool IS_SAVED = function_savebw(merged_bits.c_str(), va_MQPSK_N, data_size, "GEN_img.png");

    return calculateBER_IPP(originalBits_char.get(), merged_bits.c_str(), va_MQPSK_N * va_MQPSK_N);
}